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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/macros.cmake2
-rw-r--r--CMakeLists.txt47
-rw-r--r--SConstruct2
-rw-r--r--config/darwin-config.py9
-rw-r--r--config/irix6-config.py9
-rw-r--r--config/linux2-config.py9
-rw-r--r--config/linuxcross-config.py9
-rw-r--r--config/openbsd3-config.py9
-rw-r--r--config/sunos5-config.py9
-rw-r--r--config/win32-mingw-config.py9
-rw-r--r--config/win32-vc-config.py9
-rw-r--r--config/win64-vc-config.py9
-rw-r--r--extern/CMakeLists.txt5
-rw-r--r--extern/Makefile2
-rw-r--r--extern/SConscript4
-rw-r--r--extern/qhull/CMakeLists.txt45
-rw-r--r--extern/qhull/COPYING.txt37
-rw-r--r--extern/qhull/README.txt318
-rw-r--r--extern/qhull/REGISTER.txt37
-rw-r--r--extern/qhull/SConscript35
-rw-r--r--extern/qhull/VisualC6/qhull.dsw29
-rw-r--r--extern/qhull/VisualC6/qhull/qhull.dsp192
-rw-r--r--extern/qhull/include/qhull/geom.h177
-rw-r--r--extern/qhull/include/qhull/io.h149
-rw-r--r--extern/qhull/include/qhull/mem.h174
-rw-r--r--extern/qhull/include/qhull/merge.h171
-rw-r--r--extern/qhull/include/qhull/poly.h290
-rw-r--r--extern/qhull/include/qhull/qhull.h1048
-rw-r--r--extern/qhull/include/qhull/qhull_a.h127
-rw-r--r--extern/qhull/include/qhull/qset.h468
-rw-r--r--extern/qhull/include/qhull/stat.h520
-rw-r--r--extern/qhull/include/qhull/user.h762
-rw-r--r--extern/qhull/make/msvc_7_0/qhull.vcproj677
-rw-r--r--extern/qhull/make/msvc_9_0/qhull.vcproj877
-rwxr-xr-xextern/qhull/src/Make-config.sh285
-rw-r--r--extern/qhull/src/Makefile55
-rw-r--r--extern/qhull/src/Makefile.txt190
-rw-r--r--extern/qhull/src/geom.c1230
-rw-r--r--extern/qhull/src/geom.h177
-rw-r--r--extern/qhull/src/geom2.c2160
-rw-r--r--extern/qhull/src/global.c2018
-rw-r--r--extern/qhull/src/io.c4089
-rw-r--r--extern/qhull/src/io.h149
-rw-r--r--extern/qhull/src/mem.c447
-rw-r--r--extern/qhull/src/mem.h174
-rw-r--r--extern/qhull/src/merge.c3626
-rw-r--r--extern/qhull/src/merge.h171
-rw-r--r--extern/qhull/src/poly.c1180
-rw-r--r--extern/qhull/src/poly.h290
-rw-r--r--extern/qhull/src/poly2.c3070
-rw-r--r--extern/qhull/src/qconvex.c334
-rw-r--r--extern/qhull/src/qdelaun.c323
-rw-r--r--extern/qhull/src/qhalf.c324
-rw-r--r--extern/qhull/src/qhull.c1395
-rw-r--r--extern/qhull/src/qhull.h1048
-rw-r--r--extern/qhull/src/qhull_a.h127
-rw-r--r--extern/qhull/src/qhull_interface.cpp96
-rw-r--r--extern/qhull/src/qset.c1301
-rw-r--r--extern/qhull/src/qset.h468
-rw-r--r--extern/qhull/src/qvoronoi.c318
-rw-r--r--extern/qhull/src/rbox.c788
-rw-r--r--extern/qhull/src/stat.c700
-rw-r--r--extern/qhull/src/stat.h520
-rw-r--r--extern/qhull/src/unix.c376
-rw-r--r--extern/qhull/src/user.c324
-rw-r--r--extern/qhull/src/user.h762
-rw-r--r--extern/qhull/src/user_eg.c310
-rw-r--r--extern/qhull/src/user_eg2.c532
-rw-r--r--extern/solid/CMakeLists.txt34
-rw-r--r--extern/solid/LICENSE_GPL.txt349
-rw-r--r--extern/solid/LICENSE_QPL.txt110
-rw-r--r--extern/solid/Makefile56
-rw-r--r--extern/solid/README.txt55
-rw-r--r--extern/solid/SConscript34
-rw-r--r--extern/solid/SOLID/SOLID.h279
-rw-r--r--extern/solid/SOLID/SOLID_broad.h75
-rw-r--r--extern/solid/SOLID/SOLID_types.h53
-rw-r--r--extern/solid/VisualC6/broad/broad.dsp132
-rw-r--r--extern/solid/VisualC6/complex/complex.dsp116
-rw-r--r--extern/solid/VisualC6/convex/convex.dsp232
-rw-r--r--extern/solid/VisualC6/dynamics/dynamics.dsp120
-rw-r--r--extern/solid/VisualC6/gldemo/gldemo.dsp102
-rw-r--r--extern/solid/VisualC6/mnm/mnm.dsp100
-rw-r--r--extern/solid/VisualC6/physics/physics.dsp100
-rw-r--r--extern/solid/VisualC6/sample/sample.dsp102
-rw-r--r--extern/solid/VisualC6/solid.dsw89
-rw-r--r--extern/solid/VisualC6/solid/solid.dsp148
-rw-r--r--extern/solid/VisualC6/solid_dll/solid_dll.dsp147
-rw-r--r--extern/solid/include/GEN_MinMax.h76
-rw-r--r--extern/solid/include/GEN_random.h49
-rw-r--r--extern/solid/include/MT/Interval.h180
-rw-r--r--extern/solid/include/MT/Matrix3x3.h380
-rw-r--r--extern/solid/include/MT/Quaternion.h316
-rw-r--r--extern/solid/include/MT/Transform.h189
-rw-r--r--extern/solid/include/MT/Tuple3.h120
-rw-r--r--extern/solid/include/MT/Tuple4.h112
-rw-r--r--extern/solid/include/MT/Vector3.h283
-rw-r--r--extern/solid/include/MT_BBox.h119
-rw-r--r--extern/solid/include/MT_Interval.h33
-rw-r--r--extern/solid/include/MT_Matrix3x3.h34
-rw-r--r--extern/solid/include/MT_Point3.h31
-rw-r--r--extern/solid/include/MT_Quaternion.h35
-rw-r--r--extern/solid/include/MT_Scalar.h158
-rw-r--r--extern/solid/include/MT_Transform.h38
-rw-r--r--extern/solid/include/MT_Vector3.h50
-rw-r--r--extern/solid/include/SOLID.h279
-rw-r--r--extern/solid/include/SOLID_broad.h75
-rw-r--r--extern/solid/include/SOLID_types.h53
-rw-r--r--extern/solid/make/msvc_7_0/broad/broad.vcproj262
-rw-r--r--extern/solid/make/msvc_7_0/complex/complex.vcproj252
-rw-r--r--extern/solid/make/msvc_7_0/convex/convex.vcproj337
-rw-r--r--extern/solid/make/msvc_7_0/solid.vcproj462
-rw-r--r--extern/solid/make/msvc_9_0/broad/broad.vcproj369
-rw-r--r--extern/solid/make/msvc_9_0/complex/complex.vcproj355
-rw-r--r--extern/solid/make/msvc_9_0/convex/convex.vcproj469
-rw-r--r--extern/solid/make/msvc_9_0/solid.vcproj595
-rw-r--r--extern/solid/src/DT_AlgoTable.h47
-rw-r--r--extern/solid/src/DT_C-api.cpp581
-rw-r--r--extern/solid/src/DT_Encounter.cpp111
-rw-r--r--extern/solid/src/DT_Encounter.h84
-rw-r--r--extern/solid/src/DT_Object.cpp276
-rw-r--r--extern/solid/src/DT_Object.h157
-rw-r--r--extern/solid/src/DT_RespTable.cpp184
-rw-r--r--extern/solid/src/DT_RespTable.h139
-rw-r--r--extern/solid/src/DT_Response.h63
-rw-r--r--extern/solid/src/DT_Scene.cpp183
-rw-r--r--extern/solid/src/DT_Scene.h57
-rw-r--r--extern/solid/src/Makefile45
-rw-r--r--extern/solid/src/broad/BP_C-api.cpp77
-rw-r--r--extern/solid/src/broad/BP_Endpoint.h108
-rw-r--r--extern/solid/src/broad/BP_EndpointList.cpp237
-rw-r--r--extern/solid/src/broad/BP_EndpointList.h109
-rw-r--r--extern/solid/src/broad/BP_Proxy.cpp120
-rw-r--r--extern/solid/src/broad/BP_Proxy.h78
-rw-r--r--extern/solid/src/broad/BP_ProxyList.h69
-rw-r--r--extern/solid/src/broad/BP_Scene.cpp151
-rw-r--r--extern/solid/src/broad/BP_Scene.h79
-rw-r--r--extern/solid/src/broad/Makefile41
-rw-r--r--extern/solid/src/complex/DT_BBoxTree.cpp90
-rw-r--r--extern/solid/src/complex/DT_BBoxTree.h540
-rw-r--r--extern/solid/src/complex/DT_CBox.h134
-rw-r--r--extern/solid/src/complex/DT_Complex.cpp327
-rw-r--r--extern/solid/src/complex/DT_Complex.h94
-rw-r--r--extern/solid/src/complex/Makefile42
-rw-r--r--extern/solid/src/convex/DT_Accuracy.cpp30
-rw-r--r--extern/solid/src/convex/DT_Accuracy.h47
-rw-r--r--extern/solid/src/convex/DT_Array.h75
-rw-r--r--extern/solid/src/convex/DT_Box.cpp112
-rw-r--r--extern/solid/src/convex/DT_Box.h62
-rw-r--r--extern/solid/src/convex/DT_Cone.cpp48
-rw-r--r--extern/solid/src/convex/DT_Cone.h45
-rw-r--r--extern/solid/src/convex/DT_Convex.cpp426
-rw-r--r--extern/solid/src/convex/DT_Convex.h64
-rw-r--r--extern/solid/src/convex/DT_Cylinder.cpp39
-rw-r--r--extern/solid/src/convex/DT_Cylinder.h42
-rw-r--r--extern/solid/src/convex/DT_Facet.cpp80
-rw-r--r--extern/solid/src/convex/DT_Facet.h134
-rw-r--r--extern/solid/src/convex/DT_GJK.h438
-rw-r--r--extern/solid/src/convex/DT_Hull.h53
-rw-r--r--extern/solid/src/convex/DT_IndexArray.h33
-rw-r--r--extern/solid/src/convex/DT_LineSegment.cpp36
-rw-r--r--extern/solid/src/convex/DT_LineSegment.h52
-rw-r--r--extern/solid/src/convex/DT_Minkowski.h51
-rw-r--r--extern/solid/src/convex/DT_PenDepth.cpp376
-rw-r--r--extern/solid/src/convex/DT_PenDepth.h36
-rw-r--r--extern/solid/src/convex/DT_Point.cpp36
-rw-r--r--extern/solid/src/convex/DT_Point.h46
-rw-r--r--extern/solid/src/convex/DT_Polyhedron.cpp415
-rw-r--r--extern/solid/src/convex/DT_Polyhedron.h76
-rw-r--r--extern/solid/src/convex/DT_Polytope.cpp69
-rw-r--r--extern/solid/src/convex/DT_Polytope.h51
-rw-r--r--extern/solid/src/convex/DT_Shape.h72
-rw-r--r--extern/solid/src/convex/DT_Sphere.cpp90
-rw-r--r--extern/solid/src/convex/DT_Sphere.h43
-rw-r--r--extern/solid/src/convex/DT_Transform.h53
-rw-r--r--extern/solid/src/convex/DT_Triangle.cpp96
-rw-r--r--extern/solid/src/convex/DT_Triangle.h63
-rw-r--r--extern/solid/src/convex/DT_VertexBase.h84
-rw-r--r--extern/solid/src/convex/Makefile41
-rw-r--r--intern/bsp/test/Makefile2
-rw-r--r--intern/guardedalloc/intern/mallocn.c12
-rw-r--r--intern/iksolver/test/Makefile2
-rw-r--r--intern/moto/include/MT_Matrix3x3.h24
-rw-r--r--intern/string/intern/STR_String.cpp6
-rw-r--r--projectfiles_vc9/blender/BPY_python/BPY_python.vcproj36
-rw-r--r--projectfiles_vc9/blender/blender.sln146
-rw-r--r--projectfiles_vc9/blender/editors/ED_editors.vcproj32
-rw-r--r--projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj28
-rw-r--r--projectfiles_vc9/blender/makesrna/RNA_rna.vcproj8
-rw-r--r--projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj4
-rw-r--r--projectfiles_vc9/gameengine/converter/KX_converter.vcproj12
-rw-r--r--projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj12
-rw-r--r--projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj20
-rw-r--r--release/ui/buttons_data_armature.py4
-rw-r--r--release/ui/buttons_data_camera.py4
-rw-r--r--release/ui/buttons_data_curve.py4
-rw-r--r--release/ui/buttons_data_lamp.py4
-rw-r--r--release/ui/buttons_data_lattice.py4
-rw-r--r--release/ui/buttons_data_mesh.py48
-rw-r--r--release/ui/buttons_data_modifier.py169
-rw-r--r--release/ui/buttons_data_text.py4
-rw-r--r--release/ui/buttons_material.py4
-rw-r--r--release/ui/buttons_object_constraint.py27
-rw-r--r--release/ui/buttons_particle.py174
-rw-r--r--release/ui/buttons_physic_cloth.py48
-rw-r--r--release/ui/buttons_texture.py4
-rw-r--r--release/ui/buttons_world.py4
-rw-r--r--release/ui/space_image.py611
-rw-r--r--release/ui/space_logic.py8
-rw-r--r--release/ui/space_outliner.py4
-rw-r--r--release/ui/space_sequencer.py14
-rw-r--r--release/ui/space_text.py22
-rw-r--r--source/Makefile11
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/Makefile2
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenfont/BLF_api.h17
-rw-r--r--source/blender/blenfont/intern/blf.c25
-rw-r--r--source/blender/blenfont/intern/blf_dir.c2
-rw-r--r--source/blender/blenfont/intern/blf_font.c36
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c33
-rw-r--r--source/blender/blenfont/intern/blf_internal.h2
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h12
-rw-r--r--source/blender/blenfont/intern/blf_lang.c2
-rw-r--r--source/blender/blenkernel/BKE_cloth.h5
-rw-r--r--source/blender/blenkernel/BKE_context.h3
-rw-r--r--source/blender/blenkernel/BKE_exotic.h1
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h15
-rw-r--r--source/blender/blenkernel/BKE_particle.h7
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h57
-rw-r--r--source/blender/blenkernel/BKE_report.h2
-rw-r--r--source/blender/blenkernel/BKE_sequence.h2
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c4
-rw-r--r--source/blender/blenkernel/intern/blender.c1
-rw-r--r--source/blender/blenkernel/intern/cloth.c164
-rw-r--r--source/blender/blenkernel/intern/constraint.c8
-rw-r--r--source/blender/blenkernel/intern/context.c24
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c20
-rw-r--r--source/blender/blenkernel/intern/displist.c36
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/exotic.c594
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/idprop.c8
-rw-r--r--source/blender/blenkernel/intern/image.c2
-rw-r--r--source/blender/blenkernel/intern/implicit.c10
-rw-r--r--source/blender/blenkernel/intern/material.c4
-rw-r--r--source/blender/blenkernel/intern/modifier.c29
-rw-r--r--source/blender/blenkernel/intern/multires.c6
-rw-r--r--source/blender/blenkernel/intern/particle.c99
-rw-r--r--source/blender/blenkernel/intern/particle_system.c200
-rw-r--r--source/blender/blenkernel/intern/pointcache.c896
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c9
-rw-r--r--source/blender/blenkernel/intern/sequence.c2
-rw-r--r--source/blender/blenlib/BLI_listbase.h4
-rw-r--r--source/blender/blenlib/BLI_noise.h2
-rw-r--r--source/blender/blenlib/BLI_rect.h2
-rw-r--r--source/blender/blenlib/BLI_storage.h7
-rw-r--r--source/blender/blenlib/BLI_string.h4
-rw-r--r--source/blender/blenlib/intern/dynamiclist.c2
-rw-r--r--source/blender/blenlib/intern/dynamiclist.h2
-rw-r--r--source/blender/blenlib/intern/listbase.c2
-rw-r--r--source/blender/blenlib/intern/psfont.c4
-rw-r--r--source/blender/blenlib/intern/storage.c12
-rw-r--r--source/blender/blenlib/intern/string.c2
-rw-r--r--source/blender/blenlib/intern/util.c5
-rw-r--r--source/blender/blenloader/intern/readblenentry.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c127
-rw-r--r--source/blender/blenloader/intern/writefile.c28
-rw-r--r--source/blender/blenpluginapi/intern/Makefile4
-rw-r--r--source/blender/editors/animation/Makefile2
-rw-r--r--source/blender/editors/animation/anim_channels.c2
-rw-r--r--source/blender/editors/animation/keyframes_draw.c2
-rw-r--r--source/blender/editors/armature/BIF_generate.h2
-rw-r--r--source/blender/editors/armature/BIF_retarget.h2
-rw-r--r--source/blender/editors/armature/Makefile2
-rw-r--r--source/blender/editors/armature/editarmature_generate.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c107
-rw-r--r--source/blender/editors/armature/meshlaplacian.c2
-rw-r--r--source/blender/editors/armature/meshlaplacian.h2
-rw-r--r--source/blender/editors/curve/Makefile2
-rw-r--r--source/blender/editors/curve/curve_intern.h1
-rw-r--r--source/blender/editors/curve/curve_ops.c1
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/curve/editfont.c44
-rw-r--r--source/blender/editors/datafiles/Bfont.c2
-rw-r--r--source/blender/editors/datafiles/Makefile2
-rw-r--r--source/blender/editors/gpencil/Makefile2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2
-rw-r--r--source/blender/editors/include/BIF_gl.h2
-rw-r--r--source/blender/editors/include/ED_curve.h3
-rw-r--r--source/blender/editors/include/ED_datafiles.h2
-rw-r--r--source/blender/editors/include/ED_fluidsim.h2
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h2
-rw-r--r--source/blender/editors/include/ED_keyframing.h6
-rw-r--r--source/blender/editors/include/ED_mesh.h3
-rw-r--r--source/blender/editors/include/ED_object.h1
-rw-r--r--source/blender/editors/include/ED_particle.h2
-rw-r--r--source/blender/editors/include/ED_previewrender.h6
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h15
-rw-r--r--source/blender/editors/include/UI_resources.h2
-rw-r--r--source/blender/editors/interface/Makefile2
-rw-r--r--source/blender/editors/interface/interface.c133
-rw-r--r--source/blender/editors/interface/interface_draw.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c121
-rw-r--r--source/blender/editors/interface/interface_icons.c101
-rw-r--r--source/blender/editors/interface/interface_intern.h25
-rw-r--r--source/blender/editors/interface/interface_layout.c180
-rw-r--r--source/blender/editors/interface/interface_panel.c5
-rw-r--r--source/blender/editors/interface/interface_regions.c211
-rw-r--r--source/blender/editors/interface/interface_style.c38
-rw-r--r--source/blender/editors/interface/interface_templates.c440
-rw-r--r--source/blender/editors/interface/interface_utils.c88
-rw-r--r--source/blender/editors/interface/interface_widgets.c136
-rw-r--r--source/blender/editors/interface/resources.c2
-rw-r--r--source/blender/editors/interface/view2d.c8
-rw-r--r--source/blender/editors/mesh/Makefile2
-rw-r--r--source/blender/editors/mesh/editmesh.c4
-rw-r--r--source/blender/editors/mesh/editmesh_add.c4
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c8
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c6
-rw-r--r--source/blender/editors/object/Makefile2
-rw-r--r--source/blender/editors/object/object_edit.c27
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/physics/Makefile2
-rw-r--r--source/blender/editors/physics/editparticle.c34
-rw-r--r--source/blender/editors/physics/physics_intern.h2
-rw-r--r--source/blender/editors/preview/Makefile2
-rw-r--r--source/blender/editors/preview/previewrender.c256
-rw-r--r--source/blender/editors/screen/Makefile2
-rw-r--r--source/blender/editors/screen/area.c16
-rw-r--r--source/blender/editors/screen/glutil.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c5
-rw-r--r--source/blender/editors/sculpt_paint/Makefile2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c789
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_stroke.c2
-rw-r--r--source/blender/editors/space_action/Makefile2
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_action/action_select.c2
-rw-r--r--source/blender/editors/space_api/Makefile2
-rw-r--r--source/blender/editors/space_api/spacetypes.c2
-rw-r--r--source/blender/editors/space_buttons/Makefile2
-rw-r--r--source/blender/editors/space_buttons/SConscript3
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c9
-rw-r--r--source/blender/editors/space_buttons/buttons_header.c6
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h11
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c368
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c29
-rw-r--r--source/blender/editors/space_file/Makefile2
-rw-r--r--source/blender/editors/space_file/file_draw.c71
-rw-r--r--source/blender/editors/space_file/file_header.c2
-rw-r--r--source/blender/editors/space_file/file_ops.c2
-rw-r--r--source/blender/editors/space_file/filesel.c2
-rw-r--r--source/blender/editors/space_graph/Makefile2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_image/Makefile2
-rw-r--r--source/blender/editors/space_image/image_buttons.c44
-rw-r--r--source/blender/editors/space_image/image_draw.c28
-rw-r--r--source/blender/editors/space_image/image_header.c14
-rw-r--r--source/blender/editors/space_image/image_ops.c53
-rw-r--r--source/blender/editors/space_image/space_image.c8
-rw-r--r--source/blender/editors/space_info/Makefile2
-rw-r--r--source/blender/editors/space_info/SConscript3
-rw-r--r--source/blender/editors/space_info/info_header.c6
-rw-r--r--source/blender/editors/space_logic/Makefile2
-rw-r--r--source/blender/editors/space_logic/SConscript3
-rw-r--r--source/blender/editors/space_logic/logic_buttons.c2
-rw-r--r--source/blender/editors/space_logic/logic_header.c2
-rw-r--r--source/blender/editors/space_logic/logic_window.c102
-rw-r--r--source/blender/editors/space_nla/Makefile2
-rw-r--r--source/blender/editors/space_nla/nla_header.c2
-rw-r--r--source/blender/editors/space_node/Makefile2
-rw-r--r--source/blender/editors/space_node/node_draw.c2
-rw-r--r--source/blender/editors/space_node/node_header.c2
-rw-r--r--source/blender/editors/space_outliner/Makefile2
-rw-r--r--source/blender/editors/space_outliner/outliner.c19
-rw-r--r--source/blender/editors/space_outliner/outliner_header.c2
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c2
-rw-r--r--source/blender/editors/space_script/Makefile2
-rw-r--r--source/blender/editors/space_script/script_header.c2
-rw-r--r--source/blender/editors/space_sequencer/Makefile2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c2
-rw-r--r--source/blender/editors/space_sound/Makefile2
-rw-r--r--source/blender/editors/space_sound/sound_header.c2
-rw-r--r--source/blender/editors/space_text/Makefile2
-rw-r--r--source/blender/editors/space_text/text_header.c4
-rw-r--r--source/blender/editors/space_text/text_python.c2
-rw-r--r--source/blender/editors/space_time/Makefile2
-rw-r--r--source/blender/editors/space_time/space_time.c2
-rw-r--r--source/blender/editors/space_time/time_header.c6
-rw-r--r--source/blender/editors/space_view3d/Makefile2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c58
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c126
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c125
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c6
-rw-r--r--source/blender/editors/transform/Makefile2
-rw-r--r--source/blender/editors/transform/transform.c14
-rw-r--r--source/blender/editors/transform/transform.h1
-rw-r--r--source/blender/editors/transform/transform_conversions.c18
-rw-r--r--source/blender/editors/transform/transform_generics.c15
-rw-r--r--source/blender/editors/transform/transform_input.c3
-rw-r--r--source/blender/editors/transform/transform_ndofinput.c1
-rw-r--r--source/blender/editors/transform/transform_numinput.c1
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c19
-rw-r--r--source/blender/editors/util/Makefile2
-rw-r--r--source/blender/editors/util/undo.c2
-rw-r--r--source/blender/editors/uvedit/Makefile2
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c22
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c112
-rw-r--r--source/blender/gpu/intern/Makefile2
-rw-r--r--source/blender/imbuf/intern/imbuf.h2
-rw-r--r--source/blender/imbuf/intern/readimage.c21
-rw-r--r--source/blender/makesdna/DNA_object_force.h22
-rw-r--r--source/blender/makesdna/DNA_particle_types.h6
-rw-r--r--source/blender/makesdna/DNA_radio_types.h62
-rw-r--r--source/blender/makesdna/DNA_scene_types.h65
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h10
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h31
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/Makefile2
-rw-r--r--source/blender/makesrna/RNA_access.h35
-rw-r--r--source/blender/makesrna/RNA_define.h4
-rw-r--r--source/blender/makesrna/RNA_enum_types.h5
-rw-r--r--source/blender/makesrna/RNA_types.h21
-rw-r--r--source/blender/makesrna/intern/Makefile2
-rw-r--r--source/blender/makesrna/intern/makesrna.c105
-rw-r--r--source/blender/makesrna/intern/rna_ID.c2
-rw-r--r--source/blender/makesrna/intern/rna_access.c430
-rw-r--r--source/blender/makesrna/intern/rna_action.c2
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c2
-rw-r--r--source/blender/makesrna/intern/rna_animation.c2
-rw-r--r--source/blender/makesrna/intern/rna_armature.c27
-rw-r--r--source/blender/makesrna/intern/rna_brush.c2
-rw-r--r--source/blender/makesrna/intern/rna_camera.c2
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c45
-rw-r--r--source/blender/makesrna/intern/rna_color.c2
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c17
-rw-r--r--source/blender/makesrna/intern/rna_context.c2
-rw-r--r--source/blender/makesrna/intern/rna_controller.c2
-rw-r--r--source/blender/makesrna/intern/rna_curve.c2
-rw-r--r--source/blender/makesrna/intern/rna_define.c17
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c2
-rw-r--r--source/blender/makesrna/intern/rna_group.c2
-rw-r--r--source/blender/makesrna/intern/rna_image.c28
-rw-r--r--source/blender/makesrna/intern/rna_internal.h4
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_key.c2
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c12
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c2
-rw-r--r--source/blender/makesrna/intern/rna_main.c4
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_material.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c64
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_meta.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c60
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_object.c28
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c450
-rw-r--r--source/blender/makesrna/intern/rna_packedfile.c2
-rw-r--r--source/blender/makesrna/intern/rna_particle.c132
-rw-r--r--source/blender/makesrna/intern/rna_pose.c2
-rw-r--r--source/blender/makesrna/intern/rna_property.c2
-rw-r--r--source/blender/makesrna/intern/rna_radio.c140
-rw-r--r--source/blender/makesrna/intern/rna_rna.c18
-rw-r--r--source/blender/makesrna/intern/rna_scene.c104
-rw-r--r--source/blender/makesrna/intern/rna_screen.c2
-rw-r--r--source/blender/makesrna/intern/rna_scriptlink.c2
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c2
-rw-r--r--source/blender/makesrna/intern/rna_sequence.c2
-rw-r--r--source/blender/makesrna/intern/rna_sound.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c80
-rw-r--r--source/blender/makesrna/intern/rna_text.c2
-rw-r--r--source/blender/makesrna/intern/rna_texture.c2
-rw-r--r--source/blender/makesrna/intern/rna_timeline.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c35
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c24
-rw-r--r--source/blender/makesrna/intern/rna_vfont.c2
-rw-r--r--source/blender/makesrna/intern/rna_vpaint.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm.c204
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_world.c4
-rw-r--r--source/blender/python/BPY_extern.h4
-rw-r--r--source/blender/python/BPY_menus.c1118
-rw-r--r--source/blender/python/BPY_menus.h128
-rw-r--r--source/blender/python/Makefile2
-rw-r--r--source/blender/python/generic/BGL.c13
-rwxr-xr-xsource/blender/python/generic/BGL.h2
-rw-r--r--source/blender/python/generic/Geometry.c24
-rw-r--r--source/blender/python/generic/Geometry.h2
-rw-r--r--source/blender/python/generic/Makefile2
-rw-r--r--source/blender/python/generic/Mathutils.c247
-rw-r--r--source/blender/python/generic/Mathutils.h51
-rw-r--r--source/blender/python/generic/bpy_internal_import.c2
-rw-r--r--source/blender/python/generic/bpy_internal_import.h2
-rw-r--r--source/blender/python/generic/euler.c227
-rw-r--r--source/blender/python/generic/euler.h16
-rw-r--r--source/blender/python/generic/matrix.c323
-rw-r--r--source/blender/python/generic/matrix.h30
-rw-r--r--source/blender/python/generic/quat.c402
-rw-r--r--source/blender/python/generic/quat.h18
-rw-r--r--source/blender/python/generic/vector.c396
-rw-r--r--source/blender/python/generic/vector.h16
-rw-r--r--source/blender/python/intern/Makefile2
-rw-r--r--source/blender/python/intern/bpy_compat.h2
-rw-r--r--source/blender/python/intern/bpy_interface.c13
-rw-r--r--source/blender/python/intern/bpy_operator.c2
-rw-r--r--source/blender/python/intern/bpy_operator.h2
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c110
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h2
-rw-r--r--source/blender/python/intern/bpy_rna.c344
-rw-r--r--source/blender/python/intern/bpy_rna.h2
-rw-r--r--source/blender/python/intern/bpy_ui.c2
-rw-r--r--source/blender/python/intern/bpy_ui.h2
-rw-r--r--source/blender/python/intern/bpy_util.c4
-rw-r--r--source/blender/python/intern/bpy_util.h2
-rw-r--r--source/blender/radiosity/CMakeLists.txt36
-rw-r--r--source/blender/radiosity/Makefile34
-rw-r--r--source/blender/radiosity/SConscript12
-rw-r--r--source/blender/radiosity/extern/include/radio.h173
-rw-r--r--source/blender/radiosity/extern/include/radio_types.h168
-rw-r--r--source/blender/radiosity/intern/Makefile34
-rw-r--r--source/blender/radiosity/intern/source/Makefile55
-rw-r--r--source/blender/radiosity/intern/source/raddisplay.c477
-rw-r--r--source/blender/radiosity/intern/source/radfactors.c939
-rw-r--r--source/blender/radiosity/intern/source/radio.c390
-rw-r--r--source/blender/radiosity/intern/source/radnode.c1103
-rw-r--r--source/blender/radiosity/intern/source/radpostprocess.c824
-rw-r--r--source/blender/radiosity/intern/source/radpreprocess.c828
-rw-r--r--source/blender/radiosity/intern/source/radrender.c530
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c10
-rw-r--r--source/blender/render/intern/source/pipeline.c20
-rw-r--r--source/blender/render/intern/source/zbuf.c108
-rw-r--r--source/blender/windowmanager/WM_api.h8
-rw-r--r--source/blender/windowmanager/WM_types.h31
-rw-r--r--source/blender/windowmanager/intern/Makefile2
-rw-r--r--source/blender/windowmanager/intern/wm.c12
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c3
-rw-r--r--source/blender/windowmanager/intern/wm_files.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c313
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c21
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c2
-rw-r--r--source/blender/windowmanager/wm_cursors.h2
-rw-r--r--source/blender/windowmanager/wm_subwindow.h2
-rw-r--r--source/creator/CMakeLists.txt7
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp41
-rw-r--r--source/gameengine/BlenderRoutines/CMakeLists.txt3
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp2
-rw-r--r--source/gameengine/BlenderRoutines/Makefile4
-rw-r--r--source/gameengine/BlenderRoutines/SConscript8
-rw-r--r--source/gameengine/CMakeLists.txt1
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp49
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h9
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp13
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp40
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.h9
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp28
-rw-r--r--source/gameengine/Converter/Makefile3
-rw-r--r--source/gameengine/Converter/SConscript5
-rw-r--r--source/gameengine/Expressions/BoolValue.cpp3
-rw-r--r--source/gameengine/Expressions/CMakeLists.txt1
-rw-r--r--source/gameengine/Expressions/IntValue.cpp2
-rw-r--r--source/gameengine/Expressions/KX_Python.h2
-rw-r--r--source/gameengine/Expressions/ListValue.cpp59
-rw-r--r--source/gameengine/Expressions/ListValue.h4
-rw-r--r--source/gameengine/Expressions/Makefile1
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp338
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h99
-rw-r--r--source/gameengine/Expressions/StringValue.h2
-rw-r--r--source/gameengine/Expressions/Value.cpp124
-rw-r--r--source/gameengine/Expressions/Value.h16
-rw-r--r--source/gameengine/GameLogic/SCA_2DFilterActuator.cpp42
-rw-r--r--source/gameengine/GameLogic/SCA_2DFilterActuator.h13
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.h10
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.cpp37
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysSensor.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysSensor.h12
-rw-r--r--source/gameengine/GameLogic/SCA_DelaySensor.cpp40
-rw-r--r--source/gameengine/GameLogic/SCA_DelaySensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.h11
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.h3
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp47
-rw-r--r--source/gameengine/GameLogic/SCA_IController.h6
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp44
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.h6
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp81
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h7
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp46
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.cpp73
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp61
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp1
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.cpp47
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_NANDController.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_NANDController.h6
-rw-r--r--source/gameengine/GameLogic/SCA_NORController.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_NORController.h10
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.cpp32
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.h9
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp38
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.h8
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp42
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp63
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h6
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp48
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.h7
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.cpp46
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.h7
-rw-r--r--source/gameengine/GameLogic/SCA_XNORController.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_XNORController.h5
-rw-r--r--source/gameengine/GameLogic/SCA_XORController.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_XORController.h10
-rw-r--r--source/gameengine/GamePlayer/common/Makefile3
-rw-r--r--source/gameengine/GamePlayer/common/SConscript5
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp3
-rw-r--r--source/gameengine/GamePlayer/common/unix/Makefile2
-rw-r--r--source/gameengine/GamePlayer/ghost/SConscript4
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp43
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h6
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp37
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h7
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp43
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h7
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp43
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h9
-rw-r--r--source/gameengine/Ketsji/KX_CDActuator.cpp47
-rw-r--r--source/gameengine/Ketsji/KX_CDActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp65
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h7
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp39
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.h8
-rw-r--r--source/gameengine/Ketsji/KX_ClientObjectInfo.h12
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp50
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp42
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h5
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h30
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp592
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp445
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h42
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp37
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp56
-rw-r--r--source/gameengine/Ketsji/KX_Light.h6
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp55
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h3
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp33
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h5
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.cpp46
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.h9
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp159
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h18
-rw-r--r--source/gameengine/Ketsji/KX_OdePhysicsController.cpp257
-rw-r--r--source/gameengine/Ketsji/KX_OdePhysicsController.h109
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.cpp37
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp49
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h6
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp61
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.h2
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp44
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h7
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.cpp92
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.h55
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp38
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp213
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp40
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.h7
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp39
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h8
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_SCA_DynamicActuator.h8
-rw-r--r--source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp35
-rw-r--r--source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h6
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h9
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp88
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h10
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.cpp50
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp53
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h7
-rw-r--r--source/gameengine/Ketsji/KX_StateActuator.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_StateActuator.h9
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.cpp244
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.h122
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp44
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h7
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp51
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.h5
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp44
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.h5
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp96
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.h3
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.cpp43
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.h8
-rw-r--r--source/gameengine/Ketsji/Makefile5
-rw-r--r--source/gameengine/Ketsji/SConscript9
-rw-r--r--source/gameengine/Physics/BlOde/Makefile48
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsController.cpp625
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsController.h164
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp277
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h94
-rw-r--r--source/gameengine/Physics/BlOde/SConscript15
-rw-r--r--source/gameengine/Physics/Dummy/Makefile2
-rw-r--r--source/gameengine/Physics/Makefile3
-rw-r--r--source/gameengine/Physics/Sumo/CMakeLists.txt46
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/Makefile34
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h11
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h16
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h26
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h56
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h77
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h393
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h58
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h172
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile25
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp709
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp695
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/Makefile14
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp180
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp100
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp1298
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp378
-rw-r--r--source/gameengine/Physics/Sumo/Makefile50
-rw-r--r--source/gameengine/Physics/Sumo/SConscript25
-rw-r--r--source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp66
-rw-r--r--source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h28
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.cpp495
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.h192
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp264
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h110
-rw-r--r--source/gameengine/Physics/Sumo/convert.txt35
-rw-r--r--source/gameengine/Physics/Sumo/include/interpolator.h27
-rw-r--r--source/gameengine/Physics/common/Makefile2
-rw-r--r--source/gameengine/SConscript8
-rw-r--r--source/gameengine/VideoTexture/FilterBlueScreen.cpp20
-rw-r--r--source/gameengine/VideoTexture/FilterColor.cpp8
-rw-r--r--source/gameengine/VideoTexture/FilterNormal.cpp4
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp16
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.cpp16
-rw-r--r--source/gameengine/VideoTexture/VideoBase.cpp4
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp4
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp2
-rw-r--r--source/nan_compile.mk15
-rw-r--r--source/nan_definitions.mk41
-rw-r--r--source/nan_link.mk4
-rwxr-xr-xtools/btools.py13
783 files changed, 75617 insertions, 9734 deletions
diff --git a/CMake/macros.cmake b/CMake/macros.cmake
index 44fc2903875..bc8892e4b99 100644
--- a/CMake/macros.cmake
+++ b/CMake/macros.cmake
@@ -61,7 +61,7 @@ MACRO(SETUP_LIBLINKS
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS} ")
#TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LIB} ${PYTHON_LINKFLAGS} ${JPEG_LIB} ${PNG_LIB} ${ZLIB_LIB} ${SDL_LIB} ${LLIBS})
- TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LINKFLAGS} ${JPEG_LIBRARY} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${SDL_LIB} ${LLIBS})
+ TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LINKFLAGS} ${JPEG_LIB} ${PNG_LIB} ${ZLIB_LIB} ${SDL_LIB} ${LLIBS})
# since we are using the local libs for python when compiling msvc projects, we need to add _d when compiling debug versions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99f1c10027b..9c7ee34cc14 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -89,7 +89,7 @@ INCLUDE(CMake/macros.cmake)
IF(UNIX)
IF(WITH_OPENAL)
- FIND_PACKAGE(OpenAL)
+ INCLUDE(${CMAKE_ROOT}/Modules/FindOpenAL.cmake)
IF(OPENAL_FOUND)
SET(WITH_OPENAL ON)
SET(OPENAL_LIB ${OPENAL_LIBRARY})
@@ -102,12 +102,22 @@ IF(UNIX)
FIND_LIBRARY(INTL_LIBRARY
NAMES intl
PATHS
+ /usr/local/lib
+ /usr/lib
/sw/lib
+ /opt/local/lib
+ /opt/csw/lib
+ /opt/lib
)
FIND_LIBRARY(ICONV_LIBRARY
NAMES iconv
PATHS
+ /usr/local/lib
+ /usr/lib
/sw/lib
+ /opt/local/lib
+ /opt/csw/lib
+ /opt/lib
)
IF(INTL_LIBRARY AND ICONV_LIBRARY)
SET(GETTEXT_LIB ${INTL_LIBRARY} ${ICONV_LIBRARY})
@@ -126,14 +136,14 @@ IF(UNIX)
)
SET(FREETYPE_LIB freetype)
- FIND_PACKAGE(PythonLibs)
+ INCLUDE(${CMAKE_ROOT}/Modules/FindPythonLibs.cmake)
SET(PYTHON_INC "${PYTHON_INCLUDE_PATH}" CACHE STRING "")
SET(PYTHON_LIB "${PYTHON_LIBRARIES}" CACHE STRING "")
- FIND_PACKAGE(PythonInterp)
+ INCLUDE(${CMAKE_ROOT}/Modules/FindPythonInterp.cmake)
SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "")
SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic")
- FIND_PACKAGE(SDL)
+ INCLUDE(${CMAKE_ROOT}/Modules/FindSDL.cmake)
SET(SDL_INC ${SDL_INCLUDE_DIR})
SET(SDL_LIB ${SDL_LIBRARY})
@@ -154,11 +164,11 @@ IF(UNIX)
SET(FFMPEG_LIB avformat avcodec avutil avdevice swscale)
SET(FFMPEG_LIBPATH ${FFMPEG}/lib)
- FIND_PACKAGE(JPEG REQUIRED)
+ SET(JPEG_LIB jpeg)
- FIND_PACKAGE(PNG REQUIRED)
+ SET(PNG_LIB png)
- FIND_PACKAGE(ZLIB REQUIRED)
+ SET(ZLIB_LIB z)
SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++ -lX11 -ldl")
@@ -176,13 +186,12 @@ IF(UNIX)
# Better warnings
SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wnested-externs -Wdeclaration-after-statement")
- INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
+ INCLUDE_DIRECTORIES(/usr/include /usr/local/include)
ENDIF(UNIX)
IF(WIN32)
- # this file is included anyway when building under Windows with cl.exe
- # INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake)
+ INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake)
SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/windows)
@@ -210,15 +219,15 @@ IF(WIN32)
ENDIF(CMAKE_CL_64)
IF(CMAKE_CL_64)
- SET(PNG_LIBRARIES libpng)
+ SET(PNG_LIB libpng)
ELSE(CMAKE_CL_64)
- SET(PNG_LIBRARIES libpng_st)
+ SET(PNG_LIB libpng_st)
ENDIF(CMAKE_CL_64)
- SET(JPEG_LIBRARY libjpeg)
+ SET(JPEG_LIB libjpeg)
SET(ZLIB ${LIBDIR}/zlib)
SET(ZLIB_INC ${ZLIB}/include)
- SET(ZLIB_LIBRARIES zlib)
+ SET(ZLIB_LIB libz)
SET(ZLIB_LIBPATH ${ZLIB}/lib)
SET(PTHREADS ${LIBDIR}/pthreads)
@@ -326,7 +335,7 @@ IF(APPLE)
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
IF(WITH_OPENAL)
- FIND_PACKAGE(OpenAL)
+ INCLUDE(${CMAKE_ROOT}/Modules/FindOpenAL.cmake)
IF(OPENAL_FOUND)
SET(WITH_OPENAL ON)
SET(OPENAL_LIB ${OPENAL_LIBRARY})
@@ -353,12 +362,12 @@ IF(APPLE)
SET(GETTEXT_LIB intl iconv)
SET(GETTEXT_LIBPATH ${GETTEXT}/lib)
- SET(PNG_LIBRARIES png)
- SET(JPEG_LIBRARY jpeg)
+ SET(PNG_LIB png)
+ SET(JPEG_LIB jpeg)
SET(ZLIB /usr)
SET(ZLIB_INC "${ZLIB}/include")
- SET(ZLIB_LIBRARIES z)
+ SET(ZLIB_LIB z)
SET(FREETYPE ${LIBDIR}/freetype)
SET(FREETYPE_INC ${FREETYPE}/include ${FREETYPE}/include/freetype2)
@@ -429,7 +438,7 @@ ENDIF(WITH_WEBPLUGIN)
#-----------------------------------------------------------------------------
# Configure OpenGL.
-FIND_PACKAGE(OpenGL)
+INCLUDE(${CMAKE_ROOT}/Modules/FindOpenGL.cmake)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
#-----------------------------------------------------------------------------
# Extra compile flags
diff --git a/SConstruct b/SConstruct
index b85bc799ea5..808fa09bea0 100644
--- a/SConstruct
+++ b/SConstruct
@@ -285,7 +285,9 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_SDL'] = False
target_env_defs['WITH_BF_JPEG'] = False
target_env_defs['WITH_BF_PNG'] = False
+ target_env_defs['WITH_BF_ODE'] = False
target_env_defs['WITH_BF_BULLET'] = False
+ target_env_defs['WITH_BF_SOLID'] = False
target_env_defs['WITH_BF_BINRELOC'] = False
target_env_defs['BF_BUILDINFO'] = False
target_env_defs['BF_NO_ELBEEM'] = True
diff --git a/config/darwin-config.py b/config/darwin-config.py
index 785f1cb42a2..080820f885a 100644
--- a/config/darwin-config.py
+++ b/config/darwin-config.py
@@ -141,11 +141,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=True
WITH_BF_PLAYER=True
+WITH_BF_ODE = False
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = '${BF_ODE}/include'
+BF_ODE_LIB = '${BF_ODE}/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
#WITH_BF_NSPR = True
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
diff --git a/config/irix6-config.py b/config/irix6-config.py
index 87af6b29eb1..3c8fd0dece4 100644
--- a/config/irix6-config.py
+++ b/config/irix6-config.py
@@ -74,11 +74,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE='false'
+WITH_BF_ODE = 'false'
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = 'true'
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
#WITH_BF_NSPR = 'true'
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
diff --git a/config/linux2-config.py b/config/linux2-config.py
index 86de10c8fb3..4cea4bb8e05 100644
--- a/config/linux2-config.py
+++ b/config/linux2-config.py
@@ -77,11 +77,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
+WITH_BF_ODE = False
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
#WITH_BF_NSPR = True
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py
index 5e5c44ecd69..2f15ef67e6c 100644
--- a/config/linuxcross-config.py
+++ b/config/linuxcross-config.py
@@ -74,11 +74,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
+WITH_BF_ODE = True
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
BF_WINTAB = LIBDIR + '/wintab'
BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE'
diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py
index 2b0621e2ed3..f27066b43f7 100644
--- a/config/openbsd3-config.py
+++ b/config/openbsd3-config.py
@@ -61,11 +61,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=False
+WITH_BF_ODE = False
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = '${BF_ODE}/include'
+BF_ODE_LIB = '${BF_ODE}/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
#WITH_BF_NSPR = True
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
diff --git a/config/sunos5-config.py b/config/sunos5-config.py
index dc067b6f568..e050a5950aa 100644
--- a/config/sunos5-config.py
+++ b/config/sunos5-config.py
@@ -69,11 +69,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=False
+WITH_BF_ODE = False
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
#WITH_BF_NSPR = True
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py
index 42e56417f54..5b9b2f9b9dc 100644
--- a/config/win32-mingw-config.py
+++ b/config/win32-mingw-config.py
@@ -77,11 +77,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
+WITH_BF_ODE = True
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
BF_WINTAB = LIBDIR + '/wintab'
BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE'
diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py
index 82babeb1a3a..04e87a23ed1 100644
--- a/config/win32-vc-config.py
+++ b/config/win32-vc-config.py
@@ -90,11 +90,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
+WITH_BF_ODE = True
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
BF_WINTAB = LIBDIR + '/wintab'
BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE'
diff --git a/config/win64-vc-config.py b/config/win64-vc-config.py
index 83e27a85574..fcc6f1ab846 100644
--- a/config/win64-vc-config.py
+++ b/config/win64-vc-config.py
@@ -93,11 +93,20 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False
+WITH_BF_ODE = True
+BF_ODE = LIBDIR + '/ode'
+BF_ODE_INC = BF_ODE + '/include'
+BF_ODE_LIB = BF_ODE + '/lib/libode.a'
+
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
+BF_SOLID = '#extern/solid'
+BF_SOLID_INC = '${BF_SOLID}'
+BF_SOLID_LIB = 'extern_solid'
+
BF_WINTAB = LIBDIR + '/wintab'
BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE'
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index b6cfe3b113e..8dcace11e7d 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -24,6 +24,11 @@
#
# ***** END GPL LICENSE BLOCK *****
+IF(WITH_GAMEENGINE)
+ ADD_SUBDIRECTORY(qhull)
+ ADD_SUBDIRECTORY(solid)
+ENDIF(WITH_GAMEENGINE)
+
IF(WITH_BULLET)
ADD_SUBDIRECTORY(bullet2)
ENDIF(WITH_BULLET)
diff --git a/extern/Makefile b/extern/Makefile
index 61499da8743..8311006444f 100644
--- a/extern/Makefile
+++ b/extern/Makefile
@@ -30,7 +30,7 @@ include nan_definitions.mk
SOURCEDIR = extern
DIR = $(OCGDIR)/extern
-DIRS = glew/src
+DIRS = qhull/src solid glew/src
ifeq ($(WITH_FFMPEG), true)
ifeq ($(NAN_FFMPEG), $(LCGDIR)/ffmpeg)
diff --git a/extern/SConscript b/extern/SConscript
index 175613c3d2b..126f40b00b3 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -4,6 +4,10 @@ Import('env')
SConscript(['glew/SConscript'])
+if env['WITH_BF_GAMEENGINE']:
+ if env['WITH_BF_SOLID']:
+ SConscript(['qhull/SConscript', 'solid/SConscript'])
+
if env['WITH_BF_BULLET']:
SConscript(['bullet2/src/SConscript'])
diff --git a/extern/qhull/CMakeLists.txt b/extern/qhull/CMakeLists.txt
new file mode 100644
index 00000000000..f2ac24afff3
--- /dev/null
+++ b/extern/qhull/CMakeLists.txt
@@ -0,0 +1,45 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+SET(INC include src)
+
+SET(SRC
+ src/geom.c
+ src/geom2.c
+ src/global.c
+ src/io.c
+ src/mem.c
+ src/merge.c
+ src/poly.c
+ src/poly2.c
+ src/qhull.c
+ src/qset.c
+ src/stat.c
+ src/user.c
+)
+
+BLENDERLIB(extern_qhull "${SRC}" "${INC}")
+#, libtype=['game2','player'], priority=[50, 85]
diff --git a/extern/qhull/COPYING.txt b/extern/qhull/COPYING.txt
new file mode 100644
index 00000000000..1334eba6d0b
--- /dev/null
+++ b/extern/qhull/COPYING.txt
@@ -0,0 +1,37 @@
+ Qhull, Copyright (c) 1993-2002
+
+ The National Science and Technology Research Center for
+ Computation and Visualization of Geometric Structures
+ (The Geometry Center)
+ University of Minnesota
+ 400 Lind Hall
+ 207 Church Street S.E.
+ Minneapolis, MN 55455 USA
+
+ email: qhull@geom.umn.edu
+
+This software includes Qhull from The Geometry Center. Qhull is
+copyrighted as noted above. Qhull is free software and may be obtained
+via http from www.geom.umn.edu. It may be freely copied, modified,
+and redistributed under the following conditions:
+
+1. All copyright notices must remain intact in all files.
+
+2. A copy of this text file must be distributed along with any copies
+ of Qhull that you redistribute; this includes copies that you have
+ modified, or copies of programs or other software products that
+ include Qhull.
+
+3. If you modify Qhull, you must include a notice giving the
+ name of the person performing the modification, the date of
+ modification, and the reason for such modification.
+
+4. When distributing modified versions of Qhull, or other software
+ products that include Qhull, you must provide notice that the original
+ source code may be obtained as noted above.
+
+5. There is no warranty or other guarantee of fitness for Qhull, it is
+ provided solely "as is". Bug reports or fixes may be sent to
+ qhull_bug@geom.umn.edu; the authors may or may not act on them as
+ they desire.
+
diff --git a/extern/qhull/README.txt b/extern/qhull/README.txt
new file mode 100644
index 00000000000..9ef958a1f47
--- /dev/null
+++ b/extern/qhull/README.txt
@@ -0,0 +1,318 @@
+Name
+
+ qhull, rbox 2002.1 August 20, 2002
+
+Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection
+
+ Documentation:
+ html/index.htm
+
+ Available from:
+ <http://www.geom.umn.edu/software/qhull>
+ <http://savannah.gnu.org/projects/qhull>
+ <http://www.thesa.com/software/qhull>
+
+ Version 1 (simplicial only):
+ <http://www.geom.umn.edu/software/qhull/qhull-1.0.tar.gz>
+ <http://www.geom.umn.edu/software/qhull/qhull.sit.hqx>
+
+ News and a paper:
+ <http://www.geom.umn.edu/~bradb/qhull-news.html>
+ <http://www.geom.umn.edu/software/qhull/qhull-96.ps>
+
+Purpose
+
+ Qhull is a general dimension convex hull program that reads a set
+ of points from stdin, and outputs the smallest convex set that contains
+ the points to stdout. It also generates Delaunay triangulations, Voronoi
+ diagrams, furthest-site Voronoi diagrams, and halfspace intersections
+ about a point.
+
+ Rbox is a useful tool in generating input for Qhull; it generates
+ hypercubes, diamonds, cones, circles, simplices, spirals,
+ lattices, and random points.
+
+ Qhull produces graphical output for Geomview. This helps with
+ understanding the output. <http://www.geomview.org>
+
+
+Environment requirements
+
+ Qhull and rbox should run on all 32-bit and 64-bit computers. Use
+ an ANSI C or C++ compiler to compile the program. The software is
+ self-contained.
+
+ Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt
+ before using or distributing Qhull.
+
+To contribute to Qhull
+
+ Qhull is on Savannah, http://savannah.gnu.org/projects/qhull/
+
+Qhull on Windows 95, 98, ME, NT, 2000, XP
+
+ The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe,
+ qhalf.exe, qvoronoi.exe, documentation files, and source files.
+
+ To install Qhull:
+ - Unzip the files into a directory. You may use WinZip32 <www.hotfiles.com>
+ - Open a DOS window for the directory.
+ - In Windows 95, the DOS window needs improvement.
+ - Double-click on qhull\eg\qhull-go.bat to call doskey (arrow keys).
+ - Increase the size of the screen font to 8x12.
+ - If the text is too dim, fix the screen colors with shareware (e.g., crt.exe)
+ - If you use qhull a lot, consider using the Cygwin Unix shell,
+ Cygwin tools (http://sources.redhat.com/cygwin/)
+ - Execute 'qconvex' for a synopsis and examples.
+ - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points.
+ - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'.
+ - If an error occurs, Windows 95 sends the error to stdout instead of stderr
+ - use 'TO xxx' to send normal output to xxx and error output to stdout
+ - Browse the documentation: qhull\html\index.htm
+
+Compiling for Unix
+
+ The gzip file, qhull.tgz, contains documentation and source files for
+ qhull and rbox.
+
+ To unpack the gzip file
+ - tar zxf qhull.tgz
+ - cd qhull
+
+ Compiling with the Debian Make:[R. Laboissiere]
+ - cd src
+ - ./Make-config.sh
+ - cd ..
+ - configure
+ - make
+
+ Compiling with Makefile (i.e., Makefile.txt)
+ - cd src
+ - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines
+ - the defaults are gcc and enscript
+ - CCOPTS1 should include the ANSI flag. It defines __STDC__
+ - in user.h, check the definitions of qh_SECticks and qh_CPUclock.
+ - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour
+ - type: make
+ - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a
+ - type: make doc
+ - this prints the man page
+ - See also qhull/html/index.htm
+ - if your compiler reports many errors, it is probably not a ANSI C compiler
+ - you will need to set the -ansi switch or find another compiler
+ - if your compiler warns about missing prototypes for fprintf() etc.
+ - this is ok, your compiler should have these in stdio.h
+ - if your compiler warns about missing prototypes for memset() etc.
+ - include memory.h in qhull_a.h
+ - if your compiler is gcc-2.95.1, you need to set flag -fno-strict-aliasing.
+ - This flag is set by default for other versions [Karas, Krishnaswami]
+ - if your compiler reports "global.c: storage size of 'qh_qh' isn't known"
+ - delete the initializer "={0}" in global.c, stat.c and mem.c
+ - if your compiler warns about "stat.c: improper initializer"
+ - this is ok, the initializer is not used
+ - if you have trouble building libqhull.a with 'ar'
+ - try 'make -f Makefile.txt qhullx'
+ - if the code compiles, the qhull test case will automatically execute
+ - if an error occurs, there's an incompatibility between machines
+ - For gcc-2.95.1, you need to set flag -fno-strict-aliasing.
+ It is set by default for other versions of gcc [Karas, Krishnaswami]
+ - If you can, try a different compiler
+ - You can turn off the Qhull memory manager with qh_NOmem in mem.h
+ - You can turn off compiler optimization (-O2 in Makefile)
+ - If you find the source of the problem, please let us know
+ - if you have Geomview (www.geomview.org)
+ - try 'rbox 100 | qconvex G >a' and load 'a' into Geomview
+ - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm)
+ - to install the programs and their man pages:
+ - define MANDIR and BINDIR
+ - type 'make install'
+
+Compiling for Windows NT, 2000, XP with cygwin (www.cygwin.com)
+
+ - install cygwin with gcc, make, ar, and ln
+ - cd qhull/src
+ - make -f Makefile.txt
+
+Compiling for Windows 95, 98, NT, 2000, XP
+
+ Qhull compiles as a console application in Visual C++ 5.0 at warning
+ level 3.
+
+ Visual C++ quickstart for qhull.exe:
+ - create a "Win32 console application" called "qhull"
+ - add the following files:
+ geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c
+ qset.c stat.c unix.c user.c
+ - create a "Win32 console application" called "rbox"
+ - add rbox.c
+
+ Visual C++ quickstart for qhull library, qconvex.exe, etc.
+ - To simplify setting up lots of projects,
+ - create a temporary "Win32 console application" called "source"
+ - add all .c files from .../src/...
+ - In Tools::Options::Tab
+ Set tab size to 8 and indent size to 2
+
+ - create a "Win32 console application" called "rbox"
+ - move rbox.c from "qhull source"
+ - for Project:Settings..., Link
+ you only need the default libraries
+ - build the project
+
+ - create a "Win32 static library" called "library"
+ - move these files from "qhull source"
+ geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c
+ qset.c stat.c user.c
+ - set the library file (use the same for debug and release)
+ - build the project
+
+ - create a "Win32 console application" called "qhull"
+ - move unix.c from "qhull source"
+ - Set the library file in Project:Settings..., Link
+ - Qhull does not use other libraries
+
+ - create a "Win32 console application" called "qconvex"
+ - move qconvex.c from "qhull source"
+ - Set the library file in Project:Settings..., Link
+
+ - do the same for qdelaun.c, qhalf, qvoronoi.c, user_eg.c, user_eg2.c
+ - delete "qhull sources" since it is no longer needed
+ - Set the library file in Project:Settings..., Link
+ - use Project:Settings to make any changes
+ - use batch build to rebuild everything
+
+ Qhull compiles with Borland C++ 5.0 bcc32. A Makefile is included.
+ Execute 'make -f MBorland'. If you use the Borland IDE, set the ANSI
+ option in Options:Project:Compiler:Source:Language-compliance.
+
+ Qhull compiles with Borland C++ 4.02 for Win32 and DOS Power Pack.
+ Use 'make -f MBorland -D_DPMI'. Qhull 1.0 compiles with Borland
+ C++ 4.02. For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c".
+ Use the same options for Qhull 1.0. [D. Zwick]
+
+ Qhull compiles with Metrowerks C++ 1.7 with the ANSI option.
+
+ If you turn on full warnings, the compiler will report a number of
+ unused variables, variables set but not used, and dead code. These are
+ intentional. For example, variables may be initialized (unnecessarily)
+ to prevent warnings about possible use of uninitialized variables.
+
+Compiling for the Power Macintosh
+
+ Qhull compiles for the Power Macintosh with Metrowerk's C compiler.
+ It uses the SIOUX interface to read point coordinates and return output.
+ There is no graphical output. For project files, see 'Compiling for
+ Windows 95'. Instead of using SIOUX, Qhull may be embedded within an
+ application.
+
+ Version 1 is available for Macintosh computers by download of qhull.sit.hqx
+ It reads point coordinates from a standard file and returns output
+ to a standard file. There is no graphical output.
+
+
+Compiling for other machines
+
+ Some users have reported problems with compiling Qhull under Irix 5.1. It
+ compiles under other versions of Irix.
+
+ If you have troubles with the memory manager, you can turn it off by
+ defining qh_NOmem in mem.h.
+
+ You may compile Qhull with a C++ compiler.
+
+
+Distributed files
+
+ README.txt // instructions for installing Qhull
+ REGISTER.txt // Qhull registration
+ COPYING.txt // copyright notice
+ Announce.txt // announcement
+ Changes.txt // change history for Qhull and rbox
+ qh-faq.htm // Frequently asked questions
+ qh-home.htm // Home page
+ qh-get.htm // Download page
+ html/index.htm // Manual
+ Makefile.txt // Makefile for Unix or cygwin 'make'
+ MBorland // Makefile for Borland C++/Win32
+ Make-config.sh // Create Debian configure and automake
+
+src/
+ rbox consists of:
+ rbox.exe // Win32 executable (.zip only)
+ rbox.htm // html manual
+ rbox.man // Unix man page
+ rbox.txt
+ rbox.c // source program
+
+ qhull consists of:
+ qhull.exe // Win32 executables (.zip only)
+ qconvex.exe
+ qdelaunay.exe
+ qhalf.exe
+ qvoronoi.exe
+ qhull-go.bat // DOS window
+ qconvex.htm // html manuals
+ qdelaun.htm
+ qdelau_f.htm
+ qhalf.htm
+ qvoronoi.htm
+ qvoron_f.htm
+ qh-eg.htm
+ qh-impre.htm
+ qh-in.htm
+ index.htm
+ qh-opt*.htm
+ qh-quick.htm
+ qh--4d.gif,etc. // images for manual
+ qhull.man // Unix man page
+ qhull.txt
+ q_eg // shell script for Geomview examples
+ q_egtest // shell script for Geomview test examples
+ q_test // shell script to test qhull
+
+ top-level source files:
+ src/index.htm // index to source files
+ qh-...htm // specific files
+ user.h // header file of user definable constants
+ qhull.h // header file for qhull
+ unix.c // Unix front end to qhull
+ qhull.c // Quickhull algorithm with partitioning
+ user.c // user re-definable functions
+ user_eg.c // example of incorporating qhull into a user program
+ user_eg2.c // more complex example
+ qhull_interface.cpp // call Qhull from C++
+
+ other source files:
+ qhull_a.h // include file for *.c
+ geom.c // geometric routines
+ geom2.c
+ geom.h
+ global.c // global variables
+ io.c // input-output routines
+ io.h
+ mem.c // memory routines, this is stand-alone code
+ mem.h
+ merge.c // merging of non-convex facets
+ merge.h
+ poly.c // polyhedron routines
+ poly2.c
+ poly.h
+ qset.c // set routines, this only depends on mem.c
+ qset.h
+ stat.c // statistics
+ stat.h
+
+Authors:
+
+ C. Bradford Barber Hannu Huhdanpaa
+ bradb@geom.umn.edu hannu@geom.umn.edu
+
+ c/o The Geometry Center
+ University of Minnesota
+ 400 Lind Hall
+ 207 Church Street S.E.
+ Minneapolis, MN 55455
+
+ This software was developed under NSF grants NSF/DMS-8920161 and
+ NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard
+ University. If you find Qhull useful, please let us know.
diff --git a/extern/qhull/REGISTER.txt b/extern/qhull/REGISTER.txt
new file mode 100644
index 00000000000..767eb1c0cda
--- /dev/null
+++ b/extern/qhull/REGISTER.txt
@@ -0,0 +1,37 @@
+Dear User of Geometry Center Software:
+
+We would like to find out how you are using our software. Think of
+Geometry Center software as a new kind of shareware: you share your
+science and successes with us, and we share our software and support
+with you.
+
+If you use Geometry Center software, please send us a note telling
+us what you are doing with it.
+
+We need to know:
+
+ (1) What you are working on - an abstract of your work would be
+ fine.
+
+ (2) What Geometry Center software you use.
+
+ (3) How that software has helped you, for example, by increasing
+ your productivity or allowing you to do things you could not do
+ before. In particular, if you feel that Geometry Center
+ software has had a direct bearing on your work, please tell us
+ about this.
+
+We encourage you to cite the use of any Geometry Center software you
+have used in your publications.
+
+To cite Qhull, use
+
+ Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull
+ algorithm for convex hulls," ACM Trans. on Mathematical Software,
+ Dec 1996. http://www.geom.umn.edu/software/qhull
+
+Please send e-mail to
+
+ qhull@geom.umn.edu
+
+Thank you!
diff --git a/extern/qhull/SConscript b/extern/qhull/SConscript
new file mode 100644
index 00000000000..d3db67cddc0
--- /dev/null
+++ b/extern/qhull/SConscript
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+import sys
+import os
+
+Import('env')
+defs = ''
+cflags = []
+if sys.platform=='linux2' or sys.platform=='linux-i386':
+ cflags += ['-O2','-ansi']
+elif env['OURPLATFORM']=='win32-vc':
+ cflags += ['/O2']
+elif env['OURPLATFORM']=='win32-mingw':
+ cflags += ['-O2']
+elif sys.platform=='sunos5':
+ cflags += ['-O2', '-ansi']
+elif sys.platform=='darwin':
+ cflags += ['-O2', '-pipe', '-fPIC', '-funsigned-char', '-ffast-math']
+
+sources = ['src/geom.c',
+ 'src/geom2.c',
+ 'src/global.c',
+ 'src/io.c',
+ 'src/mem.c',
+ 'src/merge.c',
+ 'src/poly.c',
+ 'src/poly2.c',
+ 'src/qhull.c',
+ 'src/qset.c',
+ 'src/stat.c',
+ 'src/user.c']
+
+
+incs = 'include src'
+
+env.BlenderLib ( 'extern_qhull', sources, Split(incs), Split(defs), libtype=['extern'], priority=[50], compileflags = cflags)
diff --git a/extern/qhull/VisualC6/qhull.dsw b/extern/qhull/VisualC6/qhull.dsw
new file mode 100644
index 00000000000..96c68d8e34c
--- /dev/null
+++ b/extern/qhull/VisualC6/qhull.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "qhull"=".\qhull\qhull.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extern/qhull/VisualC6/qhull/qhull.dsp b/extern/qhull/VisualC6/qhull/qhull.dsp
new file mode 100644
index 00000000000..6e059b0994c
--- /dev/null
+++ b/extern/qhull/VisualC6/qhull/qhull.dsp
@@ -0,0 +1,192 @@
+# Microsoft Developer Studio Project File - Name="qhull" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=qhull - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "qhull.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "qhull.mak" CFG="qhull - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "qhull - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "qhull - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "qhull - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\lib\windows\qhull\include\qhull\ XCOPY /Y Release\*.lib ..\..\..\..\..\lib\windows\qhull\lib\
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "qhull - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\lib\windows\qhull\include\qhull\ XCOPY /Y Debug\*.lib ..\..\..\..\..\lib\windows\qhull\lib\Debug\
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "qhull - Win32 Release"
+# Name "qhull - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\geom.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\geom2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\global.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\merge.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\stat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\user.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\geom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\io.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\merge.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull_a.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qset.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\stat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\user.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/qhull/include/qhull/geom.h b/extern/qhull/include/qhull/geom.h
new file mode 100644
index 00000000000..32440cff56f
--- /dev/null
+++ b/extern/qhull/include/qhull/geom.h
@@ -0,0 +1,177 @@
+/*<html><pre> -<a href="qh-geom.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ geom.h
+ header file for geometric routines
+
+ see qh-geom.htm and geom.c
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+/* ============ -macros- ======================== */
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fabs_">-</a>
+
+ fabs_(a)
+ returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fmax_">-</a>
+
+ fmax_(a,b)
+ returns the maximum value of a and b
+*/
+#define fmax_( a,b ) ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fmin_">-</a>
+
+ fmin_(a,b)
+ returns the minimum value of a and b
+*/
+#define fmin_( a,b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="maximize_">-</a>
+
+ maximize_(maxval, val)
+ set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="minimize_">-</a>
+
+ minimize_(minval, val)
+ set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="det2_">-</a>
+
+ det2_(a1, a2,
+ b1, b2)
+
+ compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="det3_">-</a>
+
+ det3_(a1, a2, a3,
+ b1, b2, b3,
+ c1, c2, c3)
+
+ compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+ - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="dX">-</a>
+
+ dX( p1, p2 )
+ dY( p1, p2 )
+ dZ( p1, p2 )
+
+ given two indices into rows[],
+
+ compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 ) ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 ) ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 ) ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 ) ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void qh_distplane (pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+ boolT bestoutside, boolT isnewfacets, boolT noupper,
+ realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point,
+ facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist,
+ boolT bestoutside, boolT *isoutside, int *numpart);
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void qh_normalize (coordT *normal, int dim, boolT toporient);
+void qh_normalize2 (coordT *normal, int dim, boolT toporient,
+ realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void qh_setfacetplane(facetT *newfacets);
+void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0,
+ boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0,
+ boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT qh_sharpnewfacets (void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
+void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT qh_determinant (realT **rows, int dim, boolT *nearzero);
+realT qh_detjoggle (pointT *points, int numpoints, int dimension);
+void qh_detroundoff (void);
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
+realT qh_distround (int dimension, realT maxabs, realT maxsumabs);
+realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT qh_facetarea (facetT *facet);
+realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices,
+ vertexT *notvertex, boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter (setT *vertices);
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void qh_getarea (facetT *facetlist);
+boolT qh_gram_schmidt(int dim, realT **rows);
+boolT qh_inthresholds (coordT *normal, realT *angle);
+void qh_joggleinput (void);
+realT *qh_maxabsval (realT *normal, int dim);
+setT *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT qh_maxouter (void);
+void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT qh_minabsval (realT *normal, int dim);
+int qh_mindiff (realT *vecA, realT *vecB, int dim);
+boolT qh_orientoutside (facetT *facet);
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim);
+void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
+void qh_printpoints (FILE *fp, char *string, setT *points);
+void qh_projectinput (void);
+void qh_projectpoints (signed char *project, int n, realT *points,
+ int numpoints, int dim, realT *newpoints, int newdim);
+int qh_rand( void);
+void qh_srand( int seed);
+realT qh_randomfactor (void);
+void qh_randommatrix (realT *buffer, int dim, realT **row);
+void qh_rotateinput (realT **rows);
+void qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
+void qh_scaleinput (void);
+void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+ coordT high, coordT newhigh);
+void qh_scalepoints (pointT *points, int numpoints, int dim,
+ realT *newlows, realT *newhighs);
+boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp,
+ coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center (int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/extern/qhull/include/qhull/io.h b/extern/qhull/include/qhull/io.h
new file mode 100644
index 00000000000..351d56b3708
--- /dev/null
+++ b/extern/qhull/include/qhull/io.h
@@ -0,0 +1,149 @@
+/*<html><pre> -<a href="qh-io.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ io.h
+ declarations of Input/Output functions
+
+ see README, qhull.h and io.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+/*============ constants and flags ==================*/
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_MAXfirst">-</a>
+
+ qh_MAXfirst
+ maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst 200
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_MINradius">-</a>
+
+ qh_MINradius
+ min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_GEOMepsilon">-</a>
+
+ qh_GEOMepsilon
+ adjust outer planes for 'lines closer' and geomview roundoff.
+ This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_WHITESPACE">-</a>
+
+ qh_WHITESPACE
+ possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="RIDGE">-</a>
+
+ qh_RIDGE
+ to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+ qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="printvridgeT">-</a>
+
+ printvridgeT
+ prints results of qh_printvdiagram
+
+ see:
+ <a href="io.c#printvridge">qh_printvridge</a> for an example
+*/
+typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+void dfacet( unsigned id);
+void dvertex( unsigned id);
+void qh_countfacets (facetT *facetlist, setT *facets, boolT printall,
+ int *numfacetsp, int *numsimplicialp, int *totneighborsp,
+ int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT *qh_detvridge (vertexT *vertex);
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
+int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
+void qh_markkeep (facetT *facetlist);
+setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
+void qh_order_vertexneighbors(vertexT *vertex);
+void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
+void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
+void qh_printcentrum (FILE *fp, facetT *facet, realT radius);
+void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
+void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printfacet(FILE *fp, facetT *facet);
+void qh_printfacet2math(FILE *fp, facetT *facet, int notfirst);
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+ facetT *facet, realT offset, realT color[3]);
+void qh_printfacet3math (FILE *fp, facetT *facet, int notfirst);
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
+void qh_printfacetheader(FILE *fp, facetT *facet);
+void qh_printfacetridges(FILE *fp, facetT *facet);
+void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printhelp_degenerate(FILE *fp);
+void qh_printhelp_singular(FILE *fp);
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+ setT *vertices, realT color[3]);
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void qh_printpoint(FILE *fp, char *string, pointT *point);
+void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
+void qh_printpoint3 (FILE *fp, pointT *point);
+void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void qh_printridge(FILE *fp, ridgeT *ridge);
+void qh_printspheres(FILE *fp, setT *vertices, realT radius);
+void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void qh_printvertex(FILE *fp, vertexT *vertex);
+void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
+ setT *facets, boolT printall);
+void qh_printvertices (FILE *fp, char* string, setT *vertices);
+void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void qh_produce_output(void);
+void qh_projectdim3 (pointT *source, pointT *destination);
+int qh_readfeasible (int dim, char *remainder);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+void qh_setfeasible (int dim);
+boolT qh_skipfacet(facetT *facet);
+
+#endif /* qhDEFio */
diff --git a/extern/qhull/include/qhull/mem.h b/extern/qhull/include/qhull/mem.h
new file mode 100644
index 00000000000..e9ebd1bb9bc
--- /dev/null
+++ b/extern/qhull/include/qhull/mem.h
@@ -0,0 +1,174 @@
+/*<html><pre> -<a href="qh-mem.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ mem.h
+ prototypes for memory management functions
+
+ see qh-mem.htm, mem.c and qset.h
+
+ for error handling, writes message and calls
+ qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
+ and
+ qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="NOmem">-</a>
+
+ qh_NOmem
+ turn off quick-fit memory allocation
+
+ notes:
+ mem.c implements Quickfit memory allocation for about 20% time
+ savings. If it fails on your machine, try to locate the
+ problem, and send the answer to qhull@geom.umn.edu. If this can
+ not be done, define qh_NOmem to use malloc/free instead.
+
+ #define qh_NOmem
+*/
+
+/*-------------------------------------------
+ to avoid bus errors, memory allocation must consider alignment requirements.
+ malloc() automatically takes care of alignment. Since mem.c manages
+ its own memory, we need to explicitly specify alignment in
+ qh_meminitbuffers().
+
+ A safe choice is sizeof(double). sizeof(float) may be used if doubles
+ do not occur in data structures and pointers are the same size. Be careful
+ of machines (e.g., DEC Alpha) with large pointers. If gcc is available,
+ use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+ see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4 /* matches qh_ERRmem in qhull.h */
+#define qhmem_ERRqhull 5 /* matches qh_ERRqhull in qhull.h */
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="ptr_intT">-</a>
+
+ ptr_intT
+ for casting a void* to an integer-type
+
+ notes:
+ On 64-bit machines, a pointer may be larger than an 'int'.
+ qh_meminit() checks that 'long' holds a 'void*'
+*/
+typedef unsigned long ptr_intT;
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="qhmemT">-</a>
+
+ qhmemT
+ global memory structure for mem.c
+
+ notes:
+ users should ignore qhmem except for writing extensions
+ qhmem is allocated in mem.c
+
+ qhmem could be swapable like qh and qhstat, but then
+ multiple qh's and qhmem's would need to keep in synch.
+ A swapable qhmem would also waste memory buffers. As long
+ as memory operations are atomic, there is no problem with
+ multiple qh structures being active at the same time.
+ If you need separate address spaces, you can swap the
+ contents of qhmem.
+*/
+typedef struct qhmemT qhmemT;
+extern qhmemT qhmem;
+
+struct qhmemT { /* global memory management variables */
+ int BUFsize; /* size of memory allocation buffer */
+ int BUFinit; /* initial size of memory allocation buffer */
+ int TABLEsize; /* actual number of sizes in free list table */
+ int NUMsizes; /* maximum number of sizes in free list table */
+ int LASTsize; /* last size in free list table */
+ int ALIGNmask; /* worst-case alignment, must be 2^n-1 */
+ void **freelists; /* free list table, linked by offset 0 */
+ int *sizetable; /* size of each freelist */
+ int *indextable; /* size->index table */
+ void *curbuffer; /* current buffer, linked by offset 0 */
+ void *freemem; /* free memory in curbuffer */
+ int freesize; /* size of free memory in bytes */
+ void *tempstack; /* stack of temporary memory, managed by users */
+ FILE *ferr; /* file for reporting errors */
+ int IStracing; /* =5 if tracing memory allocations */
+ int cntquick; /* count of quick allocations */
+ /* remove statistics doesn't effect speed */
+ int cntshort; /* count of short allocations */
+ int cntlong; /* count of long allocations */
+ int curlong; /* current count of inuse, long allocations */
+ int freeshort; /* count of short memfrees */
+ int freelong; /* count of long memfrees */
+ int totshort; /* total size of short allocations */
+ int totlong; /* total size of long allocations */
+ int maxlong; /* maximum totlong */
+ int cntlarger; /* count of setlarger's */
+ int totlarger; /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memalloc_">-</a>
+
+ qh_memalloc_(size, object, type)
+ returns object of size bytes
+ assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#ifdef qh_NOmem
+#define qh_memalloc_(size, freelistp, object, type) {\
+ object= (type*)qh_memalloc (size); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(size, freelistp, object, type) {\
+ freelistp= qhmem.freelists + qhmem.indextable[size];\
+ if ((object= (type*)*freelistp)) {\
+ qhmem.cntquick++; \
+ *freelistp= *((void **)*freelistp);\
+ }else object= (type*)qh_memalloc (size);}
+#endif
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memfree_">-</a>
+
+ qh_memfree_(object, size)
+ free up an object
+
+ notes:
+ object may be NULL
+ assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+#ifdef qh_NOmem
+#define qh_memfree_(object, size, freelistp) {\
+ qh_memfree (object, size); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(object, size, freelistp) {\
+ if (object) { \
+ qhmem .freeshort++;\
+ freelistp= qhmem.freelists + qhmem.indextable[size];\
+ *((void **)object)= *freelistp;\
+ *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+void *qh_memalloc(int insize);
+void qh_memfree (void *object, int size);
+void qh_memfreeshort (int *curlong, int *totlong);
+void qh_meminit (FILE *ferr);
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
+ int bufsize, int bufinit);
+void qh_memsetup (void);
+void qh_memsize(int size);
+void qh_memstatistics (FILE *fp);
+
+#endif /* qhDEFmem */
diff --git a/extern/qhull/include/qhull/merge.h b/extern/qhull/include/qhull/merge.h
new file mode 100644
index 00000000000..7fc2afa5967
--- /dev/null
+++ b/extern/qhull/include/qhull/merge.h
@@ -0,0 +1,171 @@
+/*<html><pre> -<a href="qh-merge.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ merge.h
+ header file for merge.c
+
+ see qh-merge.htm and merge.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+
+/*============ -constants- ==============*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEredundant">-</a>
+
+ qh_ANGLEredundant
+ indicates redundant merge in mergeT->angle
+*/
+#define qh_ANGLEredundant 6.0
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEdegen">-</a>
+
+ qh_ANGLEdegen
+ indicates degenerate facet in mergeT->angle
+*/
+#define qh_ANGLEdegen 5.0
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEconcave">-</a>
+
+ qh_ANGLEconcave
+ offset to indicate concave facets in mergeT->angle
+
+ notes:
+ concave facets are assigned the range of [2,4] in mergeT->angle
+ roundoff error may make the angle less than 2
+*/
+#define qh_ANGLEconcave 1.5
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="MRG">-</a>
+
+ MRG... (mergeType)
+ indicates the type of a merge (mergeT->type)
+*/
+typedef enum { /* in sort order for facet_mergeset */
+ MRGnone= 0,
+ MRGcoplanar, /* centrum coplanar */
+ MRGanglecoplanar, /* angle coplanar */
+ /* could detect half concave ridges */
+ MRGconcave, /* concave ridge */
+ MRGflip, /* flipped facet. facet1 == facet2 */
+ MRGridge, /* duplicate ridge (qh_MERGEridge) */
+ /* degen and redundant go onto degen_mergeset */
+ MRGdegen, /* degenerate facet (not enough neighbors) facet1 == facet2 */
+ MRGredundant, /* redundant facet (vertex subset) */
+ /* merge_degenredundant assumes degen < redundant */
+ MRGmirror, /* mirror facet from qh_triangulate */
+ ENDmrg
+} mergeType;
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_MERGEapex">-</a>
+
+ qh_MERGEapex
+ flag for qh_mergefacet() to indicate an apex merge
+*/
+#define qh_MERGEapex True
+
+/*============ -structures- ====================*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="mergeT">-</a>
+
+ mergeT
+ structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT { /* initialize in qh_appendmergeset */
+ realT angle; /* angle between normals of facet1 and facet2 */
+ facetT *facet1; /* will merge facet1 into facet2 */
+ facetT *facet2;
+ mergeType type;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="FOREACHmerge_">-</a>
+
+ FOREACHmerge_( merges ) {...}
+ assign 'merge' to each merge in merges
+
+ notes:
+ uses 'mergeT *merge, **mergep;'
+ if qh_mergefacet(),
+ restart since qh.facet_mergeset may change
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle,
+ boolT vneighbors);
+void qh_all_merges (boolT othermerge, boolT vneighbors);
+void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
+setT *qh_basevertices( facetT *samecycle);
+void qh_checkconnect (void /* qh new_facets */);
+boolT qh_checkzero (boolT testall);
+void qh_copynonconvex (ridgeT *atridge);
+void qh_degen_redundant_facet (facetT *facet);
+void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
+void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+ facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
+void qh_forcedmerges( boolT *wasmerge);
+void qh_getmergeset(facetT *facetlist);
+void qh_getmergeset_initial (facetT *facetlist);
+void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge,
+ vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void qh_makeridges(facetT *facet);
+void qh_mark_dupridges(facetT *facetlist);
+void qh_maydropneighbor (facetT *facet);
+int qh_merge_degenredundant (void);
+void qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
+void qh_mergecycle (facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
+void qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
+void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
+void qh_mergefacet2d (facetT *facet1, facetT *facet2);
+void qh_mergeneighbors(facetT *facet1, facetT *facet2);
+void qh_mergeridges(facetT *facet1, facetT *facet2);
+void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
+void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
+void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
+void qh_mergevertices(setT *vertices1, setT **vertices);
+setT *qh_neighbor_intersections (vertexT *vertex);
+void qh_newvertices (setT *vertices);
+boolT qh_reducevertices (void);
+vertexT *qh_redundant_vertex (vertexT *vertex);
+boolT qh_remove_extravertices (facetT *facet);
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
+void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+ facetT *oldfacet, facetT *neighborA);
+boolT qh_test_appendmerge (facetT *facet, facetT *neighbor);
+boolT qh_test_vneighbors (void /* qh newfacet_list */);
+void qh_tracemerge (facetT *facet1, facetT *facet2);
+void qh_tracemerging (void);
+void qh_updatetested( facetT *facet1, facetT *facet2);
+setT *qh_vertexridges (vertexT *vertex);
+void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
+void qh_willdelete (facetT *facet, facetT *replace);
+
+#endif /* qhDEFmerge */
diff --git a/extern/qhull/include/qhull/poly.h b/extern/qhull/include/qhull/poly.h
new file mode 100644
index 00000000000..294ec9527fc
--- /dev/null
+++ b/extern/qhull/include/qhull/poly.h
@@ -0,0 +1,290 @@
+/*<html><pre> -<a href="qh-poly.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ poly.h
+ header file for poly.c and poly2.c
+
+ see qh-poly.htm, qhull.h and poly.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+/*=============== constants ========================== */
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="ALGORITHMfault">-</a>
+
+ ALGORITHMfault
+ use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="DATAfault">-</a>
+
+ DATAfault
+ use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="DUPLICATEridge">-</a>
+
+ DUPLICATEridge
+ special value for facet->neighbor to indicate a duplicate ridge
+
+ notes:
+ set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_DUPLICATEridge ( facetT * ) 1L
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="MERGEridge">-</a>
+
+ MERGEridge flag in facet
+ special value for facet->neighbor to indicate a merged ridge
+
+ notes:
+ set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_MERGEridge ( facetT * ) 2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLfacet_">-</a>
+
+ FORALLfacet_( facetlist ) { ... }
+ assign 'facet' to each facet in facetlist
+
+ notes:
+ uses 'facetT *facet;'
+ assumes last facet is a sentinel
+
+ see:
+ FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLnew_facets">-</a>
+
+ FORALLnew_facets { ... }
+ assign 'newfacet' to each facet in qh.newfacet_list
+
+ notes:
+ uses 'facetT *newfacet;'
+ at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvertex_">-</a>
+
+ FORALLvertex_( vertexlist ) { ... }
+ assign 'vertex' to each vertex in vertexlist
+
+ notes:
+ uses 'vertexT *vertex;'
+ at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvisible_facets">-</a>
+
+ FORALLvisible_facets { ... }
+ assign 'visible' to each visible facet in qh.visible_list
+
+ notes:
+ uses 'vacetT *visible;'
+ at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLsame_">-</a>
+
+ FORALLsame_( newfacet ) { ... }
+ assign 'same' to each facet in newfacet->f.samecycle
+
+ notes:
+ uses 'facetT *same;'
+ stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLsame_cycle_">-</a>
+
+ FORALLsame_cycle_( newfacet ) { ... }
+ assign 'same' to each facet in newfacet->f.samecycle
+
+ notes:
+ uses 'facetT *same;'
+ at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+ for (same= newfacet->f.samecycle; \
+ same; same= (same == newfacet ? NULL : same->f.samecycle))
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighborA_">-</a>
+
+ FOREACHneighborA_( facet ) { ... }
+ assign 'neighborA' to each neighbor in facet->neighbors
+
+ FOREACHneighborA_( vertex ) { ... }
+ assign 'neighborA' to each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighborA, **neighborAp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighborA_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvisible_">-</a>
+
+ FOREACHvisible_( facets ) { ... }
+ assign 'visible' to each facet in facets
+
+ notes:
+ uses 'facetT *facet, *facetp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHnewfacet_">-</a>
+
+ FOREACHnewfacet_( facets ) { ... }
+ assign 'newfacet' to each facet in facets
+
+ notes:
+ uses 'facetT *newfacet, *newfacetp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertexA_">-</a>
+
+ FOREACHvertexA_( vertices ) { ... }
+ assign 'vertexA' to each vertex in vertices
+
+ notes:
+ uses 'vertexT *vertexA, *vertexAp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertexreverse12_">-</a>
+
+ FOREACHvertexreverse12_( vertices ) { ... }
+ assign 'vertex' to each vertex in vertices
+ reverse order of first two vertices
+
+ notes:
+ uses 'vertexT *vertex, *vertexp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly.c in alphabetical order ================*/
+
+void qh_appendfacet(facetT *facet);
+void qh_appendvertex(vertexT *vertex);
+void qh_attachnewfacets (void);
+boolT qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
+void qh_delfacet(facetT *facet);
+void qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
+setT *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
+void qh_makenewplanes ( void /* newfacet_list */);
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
+void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
+ int *hashcount);
+void qh_matchnewfacets (void);
+boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA,
+ setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(void);
+ridgeT *qh_newridge(void);
+int qh_pointid (pointT *point);
+void qh_removefacet(facetT *facet);
+void qh_removevertex(vertexT *vertex);
+void qh_updatevertices (void);
+
+
+/*========== -prototypes poly2.c in alphabetical order ===========*/
+
+void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
+void qh_check_bestdist (void);
+void qh_check_maxout (void);
+void qh_check_output (void);
+void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
+void qh_check_points(void);
+void qh_checkconvex(facetT *facetlist, int fault);
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
+void qh_checkflipped_all (facetT *facetlist);
+void qh_checkpolygon(facetT *facetlist);
+void qh_checkvertex (vertexT *vertex);
+void qh_clearcenters (qh_CENTER type);
+void qh_createsimplex(setT *vertices);
+void qh_delridge(ridgeT *ridge);
+void qh_delvertex (vertexT *vertex);
+setT *qh_facet3vertex (facetT *facet);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+ realT *bestdist, boolT *isoutside);
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+ int *numpart);
+int qh_findgood (facetT *facetlist, int goodhorizon);
+void qh_findgood_all (facetT *facetlist);
+void qh_furthestnext (void /* qh facet_list */);
+void qh_furthestout (facetT *facet);
+void qh_infiniteloop (facetT *facet);
+void qh_initbuild(void);
+void qh_initialhull(setT *vertices);
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex (pointT *point, setT *vertices);
+vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void qh_nearcoplanar ( void /* qh.facet_list */);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+int qh_newhashtable(int newsize);
+vertexT *qh_newvertex(pointT *point);
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
+void qh_outcoplanar (void /* facet_list */);
+pointT *qh_point (int id);
+void qh_point_add (setT *set, pointT *point, void *elem);
+setT *qh_pointfacet (void /*qh facet_list*/);
+setT *qh_pointvertex (void /*qh facet_list*/);
+void qh_prependfacet(facetT *facet, facetT **facetlist);
+void qh_printhashtable(FILE *fp);
+void qh_printlists (void);
+void qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
+void qh_setvoronoi_all (void);
+void qh_triangulate (void /*qh facet_list*/);
+void qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
+void qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void qh_triangulate_mirror (facetT *facetA, facetT *facetB);
+void qh_triangulate_null (facetT *facetA);
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
+setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
+void qh_vertexneighbors (void /*qh facet_list*/);
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+
+#endif /* qhDEFpoly */
diff --git a/extern/qhull/include/qhull/qhull.h b/extern/qhull/include/qhull/qhull.h
new file mode 100644
index 00000000000..896ec1e9c18
--- /dev/null
+++ b/extern/qhull/include/qhull/qhull.h
@@ -0,0 +1,1048 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhull.h
+ user-level header file for using qhull.a library
+
+ see qh-qhull.htm, qhull_a.h
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ NOTE: access to qh_qh is via the 'qh' macro. This allows
+ qh_qh to be either a pointer or a structure. An example
+ of using qh is "qh DROPdim" which accesses the DROPdim
+ field of qh_qh. Similarly, access to qh_qhstat is via
+ the 'qhstat' macro.
+
+ includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
+
+ use mem.h for mem.c
+ use qset.h for qset.c
+
+ see unix.c for an example of using qhull.h
+
+ recompile qhull if you change this file
+*/
+
+#ifndef qhDEFqhull
+#define qhDEFqhull 1
+
+/*=========================== -included files ==============*/
+
+#include <setjmp.h>
+#include <float.h>
+#include <time.h>
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <Desk.h>
+#endif
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if !_MSC_VER
+#error Neither __STDC__ nor __cplusplus is defined. Please use strict ANSI C or C++ to compile
+#error Qhull. You may need to turn off compiler extensions in your project configuration. If
+#error your compiler is a standard C compiler, you can delete this warning from qhull.h
+#endif
+#endif
+#endif
+
+#include "user.h" /* user defineable constants */
+
+/*============ constants and basic types ====================*/
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_VERSION">-</a>
+
+ qh_VERSION
+ version string by year and date
+
+ the revision increases on code changes only
+
+ notes:
+ change date: Changes.txt, Announce.txt, README.txt, qhull.man
+ qhull-news.html, Eudora signatures,
+ change version: README.txt, qhull.html, file_id.diz, Makefile
+ change year: Copying.txt
+ check download size
+ recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
+ make copy of qhull-news.html as qh-news.htm
+*/
+
+#define qh_VERSION "2002.1 2002/8/20"
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="coordT">-</a>
+
+ coordT
+ coordinates and coefficients are stored as realT (i.e., double)
+
+ notes:
+ could use 'float' for data and 'double' for calculations (realT vs. coordT)
+ This requires many type casts, and adjusted error bounds.
+ Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="pointT">-</a>
+
+ pointT
+ a point is an array of DIM3 coordinates
+*/
+#define pointT coordT
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="flagT">-</a>
+
+ flagT
+ Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="boolT">-</a>
+
+ boolT
+ boolean value, either True or False
+
+ notes:
+ needed for portability
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="CENTERtype">-</a>
+
+ qh_CENTER
+ to distinguish facet->center
+*/
+typedef enum
+{
+ qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
+}
+qh_CENTER;
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_PRINT">-</a>
+
+ qh_PRINT
+ output formats for printing (qh.PRINTout).
+ 'Fa' 'FV' 'Fc' 'FC'
+
+
+ notes:
+ some of these names are similar to qh names. The similar names are only
+ used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0,
+ qh_PRINTarea, qh_PRINTaverage, /* 'Fa' 'FV' 'Fc' 'FC' */
+ qh_PRINTcoplanars, qh_PRINTcentrums,
+ qh_PRINTfacets, qh_PRINTfacets_xridge, /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+ qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
+ qh_PRINTnormals, qh_PRINTouter, /* 'n' 'Fo' 'i' 'm' 'Fm' 'o' */
+ qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
+ qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+ qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
+ qh_PRINTsummary, qh_PRINTtriangles, /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+ qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+ qh_PRINTEND} qh_PRINT;
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_ALL">-</a>
+
+ qh_ALL
+ argument flag for selecting everything
+*/
+#define qh_ALL True
+#define qh_NOupper True /* argument for qh_findbest */
+#define qh_IScheckmax True /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets True /* argument for qh_findbest */
+#define qh_RESETvisible True /* argument for qh_resetlists */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_ERR">-</a>
+
+ qh_ERR
+ Qhull exit codes, for indicating errors
+*/
+#define qh_ERRnone 0 /* no error occurred during qhull */
+#define qh_ERRinput 1 /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data */
+#define qh_ERRprec 3 /* precision error */
+#define qh_ERRmem 4 /* insufficient memory, matches mem.h */
+#define qh_ERRqhull 5 /* internal error detected, matches mem.h */
+
+/* ============ -structures- ====================
+ each of the following structures is defined by a typedef
+ all realT and coordT fields occur at the beginning of a structure
+ (otherwise space may be wasted due to alignment)
+ define all flags together and pack into 32-bit number
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT; /* defined in qset.h */
+#endif
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="facetT">-</a>
+
+ facetT
+ defines a facet
+
+ notes:
+ qhull() generates the hull as a list of facets.
+
+ topological information:
+ f.previous,next doubly-linked list of facets
+ f.vertices set of vertices
+ f.ridges set of ridges
+ f.neighbors set of neighbors
+ f.toporient True if facet has top-orientation (else bottom)
+
+ geometric information:
+ f.offset,normal hyperplane equation
+ f.maxoutside offset to outer plane -- all points inside
+ f.center centrum for testing convexity
+ f.simplicial True if facet is simplicial
+ f.flipped True if facet does not include qh.interior_point
+
+ for constructing hull:
+ f.visible True if facet on list of visible facets (will be deleted)
+ f.newfacet True if facet on list of newly created facets
+ f.coplanarset set of points coplanar with this facet
+ (includes near-inside points for later testing)
+ f.outsideset set of points outside of this facet
+ f.furthestdist distance to furthest point of outside set
+ f.visitid marks visited facets during a loop
+ f.replace replacement facet for to-be-deleted, visible facets
+ f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+ see below for other flags and fields
+*/
+struct facetT {
+#if !qh_COMPUTEfurthest
+ coordT furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+ coordT maxoutside; /* max computed distance of point to facet
+ Before QHULLfinished this is an approximation
+ since maxdist not always set for mergefacet
+ Actual outer plane is +DISTround and
+ computed outer plane is +2*DISTround */
+#endif
+ coordT offset; /* exact offset of hyperplane from origin */
+ coordT *normal; /* normal of hyperplane, hull_dim coefficients */
+ /* if tricoplanar, shared with a neighbor */
+ union { /* in order of testing */
+ realT area; /* area of facet, only in io.c if ->isarea */
+ facetT *replace; /* replacement facet if ->visible and NEWfacets
+ is NULL only if qh_mergedegen_redundant or interior */
+ facetT *samecycle; /* cycle of facets from the same visible/horizon intersection,
+ if ->newfacet */
+ facetT *newcycle; /* in horizon facet, current samecycle of new facets */
+ facetT *trivisible; /* visible facet for ->tricoplanar facets during qh_triangulate() */
+ facetT *triowner; /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+ }f;
+ coordT *center; /* centrum for convexity, qh CENTERtype == qh_AScentrum */
+ /* Voronoi center, qh CENTERtype == qh_ASvoronoi */
+ /* if tricoplanar, shared with a neighbor */
+ facetT *previous; /* previous facet in the facet_list */
+ facetT *next; /* next facet in the facet_list */
+ setT *vertices; /* vertices for this facet, inverse sorted by ID
+ if simplicial, 1st vertex was apex/furthest */
+ setT *ridges; /* explicit ridges for nonsimplicial facets.
+ for simplicial facets, neighbors defines ridge */
+ setT *neighbors; /* neighbors of the facet. If simplicial, the kth
+ neighbor is opposite the kth vertex, and the first
+ neighbor is the horizon facet for the first vertex*/
+ setT *outsideset; /* set of points outside this facet
+ if non-empty, last point is furthest
+ if NARROWhull, includes coplanars for partitioning*/
+ setT *coplanarset; /* set of points coplanar with this facet
+ > qh.min_vertex and <= facet->max_outside
+ a point is assigned to the furthest facet
+ if non-empty, last point is furthest away */
+ unsigned visitid; /* visit_id, for visiting all neighbors,
+ all uses are independent */
+ unsigned id; /* unique identifier from qh facet_id */
+ unsigned nummerge:9; /* number of merges */
+#define qh_MAXnummerge 511 /* 2^9-1, 32 flags total, see "flags:" in io.c */
+ flagT tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+ /* all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+ /* all tricoplanars share the same apex */
+ /* if ->degenerate, does not span facet (one logical ridge) */
+ /* one tricoplanar has ->keepcentrum and ->coplanarset */
+ /* during qh_triangulate, f.trivisible points to original facet */
+ flagT newfacet:1; /* True if facet on qh newfacet_list (new or merged) */
+ flagT visible:1; /* True if visible facet (will be deleted) */
+ flagT toporient:1; /* True if created with top orientation
+ after merging, use ridge orientation */
+ flagT simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+ flagT seen:1; /* used to perform operations only once, like visitid */
+ flagT seen2:1; /* used to perform operations only once, like visitid */
+ flagT flipped:1; /* True if facet is flipped */
+ flagT upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+ flagT notfurthest:1; /* True if last point of outsideset is not furthest*/
+
+/*-------- flags primarily for output ---------*/
+ flagT good:1; /* True if a facet marked good for output */
+ flagT isarea:1; /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+ flagT dupridge:1; /* True if duplicate ridge in facet */
+ flagT mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
+ ->normal defined (also defined for mergeridge2) */
+ flagT mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
+ flagT coplanar:1; /* True if horizon facet is coplanar at last use */
+ flagT mergehorizon:1; /* True if will merge into horizon (->coplanar) */
+ flagT cycledone:1;/* True if mergecycle_all already done */
+ flagT tested:1; /* True if facet convexity has been tested (false after merge */
+ flagT keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
+ flagT newmerge:1; /* True if facet is newly merged for reducevertices */
+ flagT degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+ flagT redundant:1; /* True if facet is redundant (degen_mergeset) */
+};
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="ridgeT">-</a>
+
+ ridgeT
+ defines a ridge
+
+ notes:
+ a ridge is DIM3-1 simplex between two neighboring facets. If the
+ facets are non-simplicial, there may be more than one ridge between
+ two facets. E.G. a 4-d hypercube has two triangles between each pair
+ of neighboring facets.
+
+ topological information:
+ vertices a set of vertices
+ top,bottom neighboring facets with orientation
+
+ geometric information:
+ tested True if ridge is clearly convex
+ nonconvex True if ridge is non-convex
+*/
+struct ridgeT {
+ setT *vertices; /* vertices belonging to this ridge, inverse sorted by ID
+ NULL if a degen ridge (matchsame) */
+ facetT *top; /* top facet this ridge is part of */
+ facetT *bottom; /* bottom facet this ridge is part of */
+ unsigned id:24; /* unique identifier, =>room for 8 flags */
+ flagT seen:1; /* used to perform operations only once */
+ flagT tested:1; /* True when ridge is tested for convexity */
+ flagT nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+ only one ridge between neighbors may have nonconvex */
+};
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="vertexT">-</a>
+
+ vertexT
+ defines a vertex
+
+ topological information:
+ next,previous doubly-linked list of all vertices
+ neighbors set of adjacent facets (only if qh.VERTEXneighbors)
+
+ geometric information:
+ point array of DIM3 coordinates
+*/
+struct vertexT {
+ vertexT *next; /* next vertex in vertex_list */
+ vertexT *previous; /* previous vertex in vertex_list */
+ pointT *point; /* hull_dim coordinates (coordT) */
+ setT *neighbors; /* neighboring facets of vertex, qh_vertexneighbors()
+ inits in io.c or after first merge */
+ unsigned visitid; /* for use with qh vertex_visit */
+ unsigned id:24; /* unique identifier, =>room for 8 flags */
+ flagT seen:1; /* used to perform operations only once */
+ flagT seen2:1; /* another seen flag */
+ flagT delridge:1; /* vertex was part of a deleted ridge */
+ flagT deleted:1; /* true if vertex on qh del_vertices */
+ flagT newlist:1; /* true if vertex on qh newvertex_list */
+};
+
+/*======= -global variables -qh ============================*/
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh">-</a>
+
+ qh
+ all global variables for qhull are in qh, qhmem, and qhstat
+
+ notes:
+ qhmem is defined in mem.h and qhstat is defined in stat.h
+ access to qh_qh is via the "qh" macro. See qh_QHpointer in user.h
+*/
+typedef struct qhT qhT;
+#if qh_QHpointer
+#define qh qh_qh->
+extern qhT *qh_qh; /* allocated in global.c */
+#else
+#define qh qh_qh.
+extern qhT qh_qh;
+#endif
+
+struct qhT {
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-const">-</a>
+
+ qh constants
+ configuration flags and constants for Qhull
+
+ notes:
+ The user configures Qhull by defining flags. They are
+ copied into qh by qh_setflags(). qh-quick.htm#options defines the flags.
+*/
+ boolT ALLpoints; /* true 'Qs' if search all points for initial simplex */
+ boolT ANGLEmerge; /* true 'Qa' if sort potential merges by angle */
+ boolT APPROXhull; /* true 'Wn' if MINoutside set */
+ realT MINoutside; /* 'Wn' min. distance for an outside point */
+ boolT ATinfinity; /* true 'Qz' if point num_points-1 is "at-infinity"
+ for improving precision in Delaunay triangulations */
+ boolT AVOIDold; /* true 'Q4' if avoid old->new merges */
+ boolT BESToutside; /* true 'Qf' if partition points into best outsideset */
+ boolT CDDinput; /* true 'Pc' if input uses CDD format (1.0/offset first) */
+ boolT CDDoutput; /* true 'PC' if print normals in CDD format (offset first) */
+ boolT CHECKfrequently; /* true 'Tc' if checking frequently */
+ realT premerge_cos; /* 'A-n' cos_max when pre merging */
+ realT postmerge_cos; /* 'An' cos_max when post merging */
+ boolT DELAUNAY; /* true 'd' if computing DELAUNAY triangulation */
+ boolT DOintersections; /* true 'Gh' if print hyperplane intersections */
+ int DROPdim; /* drops dim 'GDn' for 4-d -> 3-d output */
+ boolT FORCEoutput; /* true 'Po' if forcing output despite degeneracies */
+ int GOODpoint; /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
+ pointT *GOODpointp; /* the actual point */
+ boolT GOODthreshold; /* true if qh lower_threshold/upper_threshold defined
+ false if qh SPLITthreshold */
+ int GOODvertex; /* 1+n, good facet if vertex for point n */
+ pointT *GOODvertexp; /* the actual point */
+ boolT HALFspace; /* true 'Hn,n,n' if halfspace intersection */
+ int IStracing; /* trace execution, 0=none, 1=least, 4=most, -1=events */
+ int KEEParea; /* 'PAn' number of largest facets to keep */
+ boolT KEEPcoplanar; /* true 'Qc' if keeping nearest facet for coplanar points */
+ boolT KEEPinside; /* true 'Qi' if keeping nearest facet for inside points
+ set automatically if 'd Qc' */
+ int KEEPmerge; /* 'PMn' number of facets to keep with most merges */
+ realT KEEPminArea; /* 'PFn' minimum facet area to keep */
+ realT MAXcoplanar; /* 'Un' max distance below a facet to be coplanar*/
+ boolT MERGEexact; /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
+ boolT MERGEindependent; /* true 'Q2' if merging independent sets */
+ boolT MERGING; /* true if exact-, pre- or post-merging, with angle and centrum tests */
+ realT premerge_centrum; /* 'C-n' centrum_radius when pre merging. Default is round-off */
+ realT postmerge_centrum; /* 'Cn' centrum_radius when post merging. Default is round-off */
+ boolT MERGEvertices; /* true 'Q3' if merging redundant vertices */
+ realT MINvisible; /* 'Vn' min. distance for a facet to be visible */
+ boolT NOnarrow; /* true 'Q10' if no special processing for narrow distributions */
+ boolT NOnearinside; /* true 'Q8' if ignore near-inside points when partitioning */
+ boolT NOpremerge; /* true 'Q0' if no defaults for C-0 or Qx */
+ boolT ONLYgood; /* true 'Qg' if process points with good visible or horizon facets */
+ boolT ONLYmax; /* true 'Qm' if only process points that increase max_outside */
+ boolT PICKfurthest; /* true 'Q9' if process furthest of furthest points*/
+ boolT POSTmerge; /* true if merging after buildhull (Cn or An) */
+ boolT PREmerge; /* true if merging during buildhull (C-n or A-n) */
+ /* NOTE: some of these names are similar to qh_PRINT names */
+ boolT PRINTcentrums; /* true 'Gc' if printing centrums */
+ boolT PRINTcoplanar; /* true 'Gp' if printing coplanar points */
+ int PRINTdim; /* print dimension for Geomview output */
+ boolT PRINTdots; /* true 'Ga' if printing all points as dots */
+ boolT PRINTgood; /* true 'Pg' if printing good facets */
+ boolT PRINTinner; /* true 'Gi' if printing inner planes */
+ boolT PRINTneighbors; /* true 'PG' if printing neighbors of good facets */
+ boolT PRINTnoplanes; /* true 'Gn' if printing no planes */
+ boolT PRINToptions1st; /* true 'FO' if printing options to stderr */
+ boolT PRINTouter; /* true 'Go' if printing outer planes */
+ boolT PRINTprecision; /* false 'Pp' if not reporting precision problems */
+ qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+ boolT PRINTridges; /* true 'Gr' if print ridges */
+ boolT PRINTspheres; /* true 'Gv' if print vertices as spheres */
+ boolT PRINTstatistics; /* true 'Ts' if printing statistics to stderr */
+ boolT PRINTsummary; /* true 's' if printing summary to stderr */
+ boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+ boolT PROJECTdelaunay; /* true if DELAUNAY, no readpoints() and
+ need projectinput() for Delaunay in qh_init_B */
+ int PROJECTinput; /* number of projected dimensions 'bn:0Bn:0' */
+ boolT QUICKhelp; /* true if quick help message for degen input */
+ boolT RANDOMdist; /* true if randomly change distplane and setfacetplane */
+ realT RANDOMfactor; /* maximum random perturbation */
+ realT RANDOMa; /* qh_randomfactor is randr * RANDOMa + RANDOMb */
+ realT RANDOMb;
+ boolT RANDOMoutside; /* true if select a random outside point */
+ int REPORTfreq; /* buildtracing reports every n facets */
+ int REPORTfreq2; /* tracemerging reports every REPORTfreq/2 facets */
+ int RERUN; /* 'TRn' rerun qhull n times (qh.build_cnt) */
+ int ROTATErandom; /* 'QRn' seed, 0 time, >= rotate input */
+ boolT SCALEinput; /* true 'Qbk' if scaling input */
+ boolT SCALElast; /* true 'Qbb' if scale last coord to max prev coord */
+ boolT SETroundoff; /* true 'E' if qh DISTround is predefined */
+ boolT SKIPcheckmax; /* true 'Q5' if skip qh_check_maxout */
+ boolT SKIPconvex; /* true 'Q6' if skip convexity testing during pre-merge */
+ boolT SPLITthresholds; /* true if upper_/lower_threshold defines a region
+ used only for printing (not for qh ONLYgood) */
+ int STOPcone; /* 'TCn' 1+n for stopping after cone for point n*/
+ /* also used by qh_build_withresart for err exit*/
+ int STOPpoint; /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+ adding point n */
+ int TESTpoints; /* 'QTn' num of test points after qh.num_points. Test points always coplanar. */
+ boolT TESTvneighbors; /* true 'Qv' if test vertex neighbors at end */
+ int TRACElevel; /* 'Tn' conditional IStracing level */
+ int TRACElastrun; /* qh.TRACElevel applies to last qh.RERUN */
+ int TRACEpoint; /* 'TPn' start tracing when point n is a vertex */
+ realT TRACEdist; /* 'TWn' start tracing when merge distance too big */
+ int TRACEmerge; /* 'TMn' start tracing before this merge */
+ boolT TRIangulate; /* true 'Qt' if triangulate non-simplicial facets */
+ boolT TRInormals; /* true 'Q11' if triangulate duplicates normals (sets Qt) */
+ boolT UPPERdelaunay; /* true 'Qu' if computing furthest-site Delaunay */
+ boolT VERIFYoutput; /* true 'Tv' if verify output at end of qhull */
+ boolT VIRTUALmemory; /* true 'Q7' if depth-first processing in buildhull */
+ boolT VORONOI; /* true 'v' if computing Voronoi diagram */
+
+ /*--------input constants ---------*/
+ realT AREAfactor; /* 1/(hull_dim-1)! for converting det's to area */
+ boolT DOcheckmax; /* true if calling qh_check_maxout (qh_initqhull_globals) */
+ char *feasible_string; /* feasible point 'Hn,n,n' for halfspace intersection */
+ coordT *feasible_point; /* as coordinates, both malloc'd */
+ boolT GETarea; /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
+ boolT KEEPnearinside; /* true if near-inside points in coplanarset */
+ int hull_dim; /* dimension of hull, set by initbuffers */
+ int input_dim; /* dimension of input, set by initbuffers */
+ int num_points; /* number of input points */
+ pointT *first_point; /* array of input points, see POINTSmalloc */
+ boolT POINTSmalloc; /* true if qh first_point/num_points allocated */
+ pointT *input_points; /* copy of original qh.first_point for input points for qh_joggleinput */
+ boolT input_malloc; /* true if qh input_points malloc'd */
+ char qhull_command[256];/* command line that invoked this program */
+ char rbox_command[256]; /* command line that produced the input points */
+ char qhull_options[512];/* descriptive list of options */
+ int qhull_optionlen; /* length of last line */
+ int qhull_optionsiz; /* size of qhull_options before qh_initbuild */
+ boolT VERTEXneighbors; /* true if maintaining vertex neighbors */
+ boolT ZEROcentrum; /* true if 'C-0' or 'C-0 Qx'. sets ZEROall_ok */
+ realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+ must set either GOODthreshold or SPLITthreshold
+ if Delaunay, default is 0.0 for upper envelope */
+ realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+ realT *upper_bound; /* scale point[k] to new upper bound */
+ realT *lower_bound; /* scale point[k] to new lower bound
+ project if both upper_ and lower_bound == 0 */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-prec">-</a>
+
+ qh precision constants
+ precision constants for Qhull
+
+ notes:
+ qh_detroundoff() computes the maximum roundoff error for distance
+ and other computations. It also sets default values for the
+ qh constants above.
+*/
+ realT ANGLEround; /* max round off error for angles */
+ realT centrum_radius; /* max centrum radius for convexity (roundoff added) */
+ realT cos_max; /* max cosine for convexity (roundoff added) */
+ realT DISTround; /* max round off error for distances, 'E' overrides */
+ realT MAXabs_coord; /* max absolute coordinate */
+ realT MAXlastcoord; /* max last coordinate for qh_scalelast */
+ realT MAXsumcoord; /* max sum of coordinates */
+ realT MAXwidth; /* max rectilinear width of point coordinates */
+ realT MINdenom_1; /* min. abs. value for 1/x */
+ realT MINdenom; /* use divzero if denominator < MINdenom */
+ realT MINdenom_1_2; /* min. abs. val for 1/x that allows normalization */
+ realT MINdenom_2; /* use divzero if denominator < MINdenom_2 */
+ realT MINlastcoord; /* min. last coordinate for qh_scalelast */
+ boolT NARROWhull; /* set in qh_initialhull if angle < qh_MAXnarrow */
+ realT *NEARzero; /* hull_dim array for near zero in gausselim */
+ realT NEARinside; /* keep points for qh_check_maxout if close to facet */
+ realT ONEmerge; /* max distance for merging simplicial facets */
+ realT outside_err; /* application's epsilon for coplanar points
+ qh_check_bestdist() qh_check_points() reports error if point outside */
+ realT WIDEfacet; /* size of wide facet for skipping ridge in
+ area computation and locking centrum */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-intern">-</a>
+
+ qh internal constants
+ internal constants for Qhull
+*/
+ char qhull[sizeof("qhull")]; /* for checking ownership */
+ void *old_stat; /* pointer to saved qh_qhstat, qh_save_qhull */
+ jmp_buf errexit; /* exit label for qh_errexit, defined by setjmp() */
+ char jmpXtra[40]; /* extra bytes in case jmp_buf is defined wrong by compiler */
+ jmp_buf restartexit; /* restart label for qh_errexit, defined by setjmp() */
+ char jmpXtra2[40]; /* extra bytes in case jmp_buf is defined wrong by compiler*/
+ FILE *fin; /* pointer to input file, init by qh_meminit */
+ FILE *fout; /* pointer to output file */
+ FILE *ferr; /* pointer to error file */
+ pointT *interior_point; /* center point of the initial simplex*/
+ int normal_size; /* size in bytes for facet normals and point coords*/
+ int center_size; /* size in bytes for Voronoi centers */
+ int TEMPsize; /* size for small, temporary sets (in quick mem) */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-lists">-</a>
+
+ qh facet and vertex lists
+ defines lists of facets, new facets, visible facets, vertices, and
+ new vertices. Includes counts, next ids, and trace ids.
+ see:
+ qh_resetlists()
+*/
+ facetT *facet_list; /* first facet */
+ facetT *facet_tail; /* end of facet_list (dummy facet) */
+ facetT *facet_next; /* next facet for buildhull()
+ previous facets do not have outside sets
+ NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+ facetT *newfacet_list; /* list of new facets to end of facet_list */
+ facetT *visible_list; /* list of visible facets preceeding newfacet_list,
+ facet->visible set */
+ int num_visible; /* current number of visible facets */
+ unsigned tracefacet_id; /* set at init, then can print whenever */
+ facetT *tracefacet; /* set in newfacet/mergefacet, undone in delfacet*/
+ unsigned tracevertex_id; /* set at buildtracing, can print whenever */
+ vertexT *tracevertex; /* set in newvertex, undone in delvertex*/
+ vertexT *vertex_list; /* list of all vertices, to vertex_tail */
+ vertexT *vertex_tail; /* end of vertex_list (dummy vertex) */
+ vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+ all vertices have 'newlist' set */
+ int num_facets; /* number of facets in facet_list
+ includes visble faces (num_visible) */
+ int num_vertices; /* number of vertices in facet_list */
+ int num_outside; /* number of points in outsidesets (for tracing and RANDOMoutside)
+ includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+ int num_good; /* number of good facets (after findgood_all) */
+ unsigned facet_id; /* ID of next, new facet from newfacet() */
+ unsigned ridge_id; /* ID of next, new ridge from newridge() */
+ unsigned vertex_id; /* ID of next, new vertex from newvertex() */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-var">-</a>
+
+ qh global variables
+ defines minimum and maximum distances, next visit ids, several flags,
+ and other global variables.
+ initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+ unsigned long hulltime; /* ignore time to set up input and randomize */
+ /* use unsigned to avoid wrap-around errors */
+ boolT ALLOWrestart; /* true if qh_precision can use qh.restartexit */
+ int build_cnt; /* number of calls to qh_initbuild */
+ qh_CENTER CENTERtype; /* current type of facet->center, qh_CENTER */
+ int furthest_id; /* pointid of furthest point, for tracing */
+ facetT *GOODclosest; /* closest facet to GOODthreshold in qh_findgood */
+ realT JOGGLEmax; /* set 'QJn' if randomly joggle input */
+ boolT maxoutdone; /* set qh_check_maxout(), cleared by qh_addpoint() */
+ realT max_outside; /* maximum distance from a point to a facet,
+ before roundoff, not simplicial vertices
+ actual outer plane is +DISTround and
+ computed outer plane is +2*DISTround */
+ realT max_vertex; /* maximum distance (>0) from vertex to a facet,
+ before roundoff, due to a merge */
+ realT min_vertex; /* minimum distance (<0) from vertex to a facet,
+ before roundoff, due to a merge
+ if qh.JOGGLEmax, qh_makenewplanes sets it
+ recomputed if qh.DOcheckmax, default -qh.DISTround */
+ boolT NEWfacets; /* true while visible facets invalid due to new or merge
+ from makecone/attachnewfacets to deletevisible */
+ boolT findbestnew; /* true if partitioning calls qh_findbestnew */
+ boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+ boolT NOerrexit; /* true if qh.errexit is not available */
+ realT PRINTcradius; /* radius for printing centrums */
+ realT PRINTradius; /* radius for printing vertex spheres and points */
+ boolT POSTmerging; /* true when post merging */
+ int printoutvar; /* temporary variable for qh_printbegin, etc. */
+ int printoutnum; /* number of facets printed */
+ boolT QHULLfinished; /* True after qhull() is finished */
+ realT totarea; /* 'FA': total facet area computed by qh_getarea */
+ realT totvol; /* 'FA': total volume computed by qh_getarea */
+ unsigned int visit_id; /* unique ID for searching neighborhoods, */
+ unsigned int vertex_visit; /* unique ID for searching vertices */
+ boolT ZEROall_ok; /* True if qh_checkzero always succeeds */
+ boolT WAScoplanar; /* True if qh_partitioncoplanar (qh_check_maxout) */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-set">-</a>
+
+ qh global sets
+ defines sets for merging, initial simplex, hashing, extra input points,
+ and deleted vertices
+*/
+ setT *facet_mergeset; /* temporary set of merges to be done */
+ setT *degen_mergeset; /* temporary set of degenerate and redundant merges */
+ setT *hash_table; /* hash table for matching ridges in qh_matchfacets
+ size is setsize() */
+ setT *other_points; /* additional points (first is qh interior_point) */
+ setT *del_vertices; /* vertices to partition and delete with visible
+ facets. Have deleted set for checkfacet */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-buf">-</a>
+
+ qh global buffers
+ defines buffers for maxtrix operations, input, and error messages
+*/
+ coordT *gm_matrix; /* (dim+1)Xdim matrix for geom.c */
+ coordT **gm_row; /* array of gm_matrix rows */
+ char* line; /* malloc'd input line of maxline+1 chars */
+ int maxline;
+ coordT *half_space; /* malloc'd input array for halfspace (qh normal_size+coordT) */
+ coordT *temp_malloc; /* malloc'd input array for points */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-static">-</a>
+
+ qh static variables
+ defines static variables for individual functions
+
+ notes:
+ do not use 'static' within a function. Multiple instances of qhull
+ may exist.
+
+ do not assume zero initialization, 'QPn' may cause a restart
+*/
+ boolT ERREXITcalled; /* true during errexit (prevents duplicate calls */
+ boolT firstcentrum; /* for qh_printcentrum */
+ realT last_low; /* qh_scalelast parameters for qh_setdelaunay */
+ realT last_high;
+ realT last_newhigh;
+ unsigned lastreport; /* for qh_buildtracing */
+ int mergereport; /* for qh_tracemerging */
+ boolT old_randomdist; /* save RANDOMdist when io, tracing, or statistics */
+ int ridgeoutnum; /* number of ridges in 4OFF output */
+ void *old_qhstat; /* for saving qh_qhstat in save_qhull() */
+ setT *old_tempstack; /* for saving qhmem.tempstack in save_qhull */
+ setT *coplanarset; /* set of coplanar facets for searching qh_findbesthorizon() */
+};
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="otherfacet_">-</a>
+
+ otherfacet_(ridge, facet)
+ return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+ (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="getid_">-</a>
+
+ getid_(p)
+ return ID for facet, ridge, or vertex
+ return MAXINT if NULL (-1 causes type conversion error )
+*/
+#define getid_(p) ((p) ? (p)->id : -1)
+
+/*============== FORALL macros ===================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLfacets">-</a>
+
+ FORALLfacets { ... }
+ assign 'facet' to each facet in qh.facet_list
+
+ notes:
+ uses 'facetT *facet;'
+ assumes last facet is a sentinel
+
+ see:
+ FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLpoints">-</a>
+
+ FORALLpoints { ... }
+ assign 'point' to each point in qh.first_point, qh.num_points
+
+ declare:
+ coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLpoint_">-</a>
+
+ FORALLpoint_( points, num) { ... }
+ assign 'point' to each point in points array of num points
+
+ declare:
+ coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(points, num) for(point= (points), \
+ pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvertices">-</a>
+
+ FORALLvertices { ... }
+ assign 'vertex' to each vertex in qh.vertex_list
+
+ declare:
+ vertexT *vertex;
+
+ notes:
+ assumes qh.vertex_list terminated with a sentinel
+*/
+#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHfacet_">-</a>
+
+ FOREACHfacet_( facets ) { ... }
+ assign 'facet' to each facet in facets
+
+ declare:
+ facetT *facet, **facetp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighbor_">-</a>
+
+ FOREACHneighbor_( facet ) { ... }
+ assign 'neighbor' to each neighbor in facet->neighbors
+
+ FOREACHneighbor_( vertex ) { ... }
+ assign 'neighbor' to each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighbor, **neighborp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighbor_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHpoint_">-</a>
+
+ FOREACHpoint_( points ) { ... }
+ assign 'point' to each point in points set
+
+ declare:
+ pointT *point, **pointp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHpoint_(points) FOREACHsetelement_(pointT, points, point)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHridge_">-</a>
+
+ FOREACHridge_( ridges ) { ... }
+ assign 'ridge' to each ridge in ridges set
+
+ declare:
+ ridgeT *ridge, **ridgep;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHridge_(ridges) FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertex_">-</a>
+
+ FOREACHvertex_( vertices ) { ... }
+ assign 'vertex' to each vertex in vertices set
+
+ declare:
+ vertexT *vertex, **vertexp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHfacet_i_">-</a>
+
+ FOREACHfacet_i_( facets ) { ... }
+ assign 'facet' and 'facet_i' for each facet in facets set
+
+ declare:
+ facetT *facet;
+ int facet_n, facet_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHfacet_i_(facets) FOREACHsetelement_i_(facetT, facets, facet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighbor_i_">-</a>
+
+ FOREACHneighbor_i_( facet ) { ... }
+ assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+ FOREACHneighbor_i_( vertex ) { ... }
+ assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighbor;
+ int neighbor_n, neighbor_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHneighbor_i_(facet) FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHpoint_i_">-</a>
+
+ FOREACHpoint_i_( points ) { ... }
+ assign 'point' and 'point_i' for each point in points set
+
+ declare:
+ pointT *point;
+ int point_n, point_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHpoint_i_(points) FOREACHsetelement_i_(pointT, points, point)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHridge_i_">-</a>
+
+ FOREACHridge_i_( ridges ) { ... }
+ assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+ declare:
+ ridgeT *ridge;
+ int ridge_n, ridge_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHridge_i_(ridges) FOREACHsetelement_i_(ridgeT, ridges, ridge)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertex_i_">-</a>
+
+ FOREACHvertex_i_( vertices ) { ... }
+ assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+ declare:
+ vertexT *vertex;
+ int vertex_n, vertex_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+ */
+#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
+
+/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
+
+void qh_qhull (void);
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void qh_printsummary(FILE *fp);
+
+/********* -user.c prototypes (alphabetical) **********************/
+
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
+void qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
+ char *qhull_cmd, FILE *outfile, FILE *errfile);
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
+void qh_user_memsizes (void);
+
+/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
+
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+ boolT bestoutside, boolT newfacets, boolT noupper,
+ realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+ realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT qh_gram_schmidt(int dim, realT **rows);
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+void qh_printsummary(FILE *fp);
+void qh_projectinput (void);
+void qh_randommatrix (realT *buffer, int dim, realT **row);
+void qh_rotateinput (realT **rows);
+void qh_scaleinput (void);
+void qh_setdelaunay (int dim, int count, pointT *points);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock (void);
+void qh_checkflags (char *command, char *hiddenflags);
+void qh_freebuffers (void);
+void qh_freeqhull (boolT allmem);
+void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_init_qhull_command (int argc, char *argv[]);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_initflags (char *command);
+void qh_initqhull_buffers (void);
+void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_initqhull_mem (void);
+void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
+void qh_initthresholds (char *command);
+void qh_option (char *option, int *i, realT *r);
+#if qh_QHpointer
+void qh_restore_qhull (qhT **oldqh);
+qhT *qh_save_qhull (void);
+#endif
+
+/***** -io.c prototypes (duplicated from io.h) ***********************/
+
+void dfacet( unsigned id);
+void dvertex( unsigned id);
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void qh_produce_output(void);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -mem.c prototypes (duplicated from mem.h) **********************/
+
+void qh_meminit (FILE *ferr);
+void qh_memfreeshort (int *curlong, int *totlong);
+
+/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
+
+void qh_check_output (void);
+void qh_check_points (void);
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+ realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point (int id);
+setT *qh_pointfacet (void /*qh.facet_list*/);
+int qh_pointid (pointT *point);
+setT *qh_pointvertex (void /*qh.facet_list*/);
+void qh_setvoronoi_all (void);
+void qh_triangulate (void /*qh facet_list*/);
+
+/********* -stat.c prototypes (duplicated from stat.h) **********************/
+
+void qh_collectstatistics (void);
+void qh_printallstatistics (FILE *fp, char *string);
+
+#endif /* qhDEFqhull */
diff --git a/extern/qhull/include/qhull/qhull_a.h b/extern/qhull/include/qhull/qhull_a.h
new file mode 100644
index 00000000000..d4e69b071be
--- /dev/null
+++ b/extern/qhull/include/qhull/qhull_a.h
@@ -0,0 +1,127 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhull_a.h
+ all header files for compiling qhull
+
+ see qh-qhull.htm
+
+ see qhull.h for user-level definitions
+
+ see user.h for user-defineable constants
+
+ defines internal functions for qhull.c global.c
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ Notes: grep for ((" and (" to catch fprintf("lkasdjf");
+ full parens around (x?y:z)
+ use '#include qhull/qhull_a.h' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+#include <math.h>
+#include <float.h> /* some compilers will not need float.h */
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+/*** uncomment here and qset.c
+ if string.h does not define memcpy()
+#include <memory.h>
+*/
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+#include "geom.h"
+#include "merge.h"
+#include "poly.h"
+#include "io.h"
+#include "stat.h"
+
+#if qh_CLOCKtype == 2 /* defined in user.h from qhull.h */
+#include <sys/types.h>
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+
+#ifdef _MSC_VER /* Microsoft Visual C++ */
+#pragma warning( disable : 4056) /* float constant expression. Looks like a compiler bug */
+#pragma warning( disable : 4146) /* unary minus applied to unsigned type */
+#pragma warning( disable : 4244) /* conversion from 'unsigned long' to 'real' */
+#pragma warning( disable : 4305) /* conversion from 'const double' to 'float' */
+#endif
+
+/* ======= -macros- =========== */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="traceN">-</a>
+
+ traceN((fp.ferr, "format\n", vars));
+ calls fprintf if qh.IStracing >= N
+
+ notes:
+ removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh IStracing) fprintf args;}
+#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
+#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
+#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
+#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
+#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/***** -qhull.c prototypes (alphabetical after qhull) ********************/
+
+void qh_qhull (void);
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void qh_buildhull(void);
+void qh_buildtracing (pointT *furthest, facetT *facet);
+void qh_build_withrestart (void);
+void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
+void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest (facetT **visible);
+void qh_partitionall(setT *vertices, pointT *points,int npoints);
+void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
+void qh_partitionpoint (pointT *point, facetT *facet);
+void qh_partitionvisible(boolT allpoints, int *numpoints);
+void qh_precision (char *reason);
+void qh_printsummary(FILE *fp);
+
+/***** -global.c internal prototypes (alphabetical) ***********************/
+
+void qh_appendprint (qh_PRINT format);
+void qh_freebuild (boolT allmem);
+void qh_freebuffers (void);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+int qh_strtol (const char *s, char **endp);
+double qh_strtod (const char *s, char **endp);
+
+/***** -stat.c internal prototypes (alphabetical) ***********************/
+
+void qh_allstatA (void);
+void qh_allstatB (void);
+void qh_allstatC (void);
+void qh_allstatD (void);
+void qh_allstatE (void);
+void qh_allstatE2 (void);
+void qh_allstatF (void);
+void qh_allstatG (void);
+void qh_allstatH (void);
+void qh_freebuffers (void);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#endif /* qhDEFqhulla */
diff --git a/extern/qhull/include/qhull/qset.h b/extern/qhull/include/qhull/qset.h
new file mode 100644
index 00000000000..6c0ff758de4
--- /dev/null
+++ b/extern/qhull/include/qhull/qset.h
@@ -0,0 +1,468 @@
+/*<html><pre> -<a href="qh-set.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qset.h
+ header file for qset.c that implements set
+
+ see qh-set.htm and qset.c
+
+ only uses mem.c, malloc/free
+
+ for error handling, writes message and calls
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+
+ set operations satisfy the following properties:
+ - sets have a max size, the actual size (if different) is stored at the end
+ - every set is NULL terminated
+ - sets may be sorted or unsorted, the caller must distinguish this
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */
+#endif
+
+/*-<a href="qh-set.htm#TOC"
+>----------------------------------------</a><a name="setT">-</a>
+
+setT
+ a set or list of pointers with maximum size and actual size.
+
+variations:
+ unsorted, unique -- a list of unique pointers with NULL terminator
+ user guarantees uniqueness
+ sorted -- a sorted list of unique pointers with NULL terminator
+ qset.c guarantees uniqueness
+ unsorted -- a list of pointers terminated with NULL
+ indexed -- an array of pointers with NULL elements
+
+structure for set of n elements:
+
+ --------------
+ | maxsize
+ --------------
+ | e[0] - a pointer, may be NULL for indexed sets
+ --------------
+ | e[1]
+
+ --------------
+ | ...
+ --------------
+ | e[n-1]
+ --------------
+ | e[n] = NULL
+ --------------
+ | ...
+ --------------
+ | e[maxsize] - n+1 or NULL (determines actual size of set)
+ --------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+ void *p;
+ int i; /* integer used for e[maxSize] */
+};
+
+struct setT {
+ int maxsize; /* maximum number of elements (except NULL) */
+ setelemT e[1]; /* array of pointers, tail is NULL */
+ /* last slot (unless NULL) is actual size+1
+ e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+ /* this may generate a warning since e[] contains
+ maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="SETelemsize">-</a>
+
+ SETelemsize
+ size of a set element in bytes
+*/
+#define SETelemsize sizeof(setelemT)
+
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHsetelement_">-</a>
+
+ FOREACHsetelement_(type, set, variable)
+ define FOREACH iterator
+
+ declare:
+ assumes *variable and **variablep are declared
+ no space in "variable)" [DEC Alpha cc compiler]
+
+ each iteration:
+ variable is set element
+ variablep is one beyond variable.
+
+ to repeat an element:
+ variablep--; / *repeat* /
+
+ at exit:
+ variable is NULL at end of loop
+
+ example:
+ #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
+
+ notes:
+ use FOREACHsetelement_i_() if need index or include NULLs
+
+ WARNING:
+ nested loops can't use the same variable (define another FOREACH)
+
+ needs braces if nested inside another FOREACH
+ this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##p= (type **)&((set)->e[0].p); \
+ (variable= *variable##p++);)
+
+/*-<a href="qh-set.htm#TOC"
+ >----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
+
+ FOREACHsetelement_i_(type, set, variable)
+ define indexed FOREACH iterator
+
+ declare:
+ type *variable, variable_n, variable_i;
+
+ each iteration:
+ variable is set element, may be NULL
+ variable_i is index, variable_n is qh_setsize()
+
+ to repeat an element:
+ variable_i--; variable_n-- repeats for deleted element
+
+ at exit:
+ variable==NULL and variable_i==variable_n
+
+ example:
+ #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
+
+ WARNING:
+ nested loops can't use the same variable (define another FOREACH)
+
+ needs braces if nested inside another FOREACH
+ this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(type, set, variable) \
+ if (((variable= NULL), set)) for (\
+ variable##_i= 0, variable= (type *)((set)->e[0].p), \
+ variable##_n= qh_setsize(set);\
+ variable##_i < variable##_n;\
+ variable= (type *)((set)->e[++variable##_i].p) )
+
+/*-<a href="qh-set.htm#TOC"
+ >--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
+
+ FOREACHsetelementreverse_(type, set, variable)-
+ define FOREACH iterator in reverse order
+
+ declare:
+ assumes *variable and **variablep are declared
+ also declare 'int variabletemp'
+
+ each iteration:
+ variable is set element
+
+ to repeat an element:
+ variabletemp++; / *repeat* /
+
+ at exit:
+ variable is NULL
+
+ example:
+ #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
+
+ notes:
+ use FOREACHsetelementreverse12_() to reverse first two elements
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
+ variable; variable= \
+ ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a>
+
+ FOREACHsetelementreverse12_(type, set, variable)-
+ define FOREACH iterator with e[1] and e[0] reversed
+
+ declare:
+ assumes *variable and **variablep are declared
+
+ each iteration:
+ variable is set element
+ variablep is one after variable.
+
+ to repeat an element:
+ variablep--; / *repeat* /
+
+ at exit:
+ variable is NULL at end of loop
+
+ example
+ #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##p= (type **)&((set)->e[1].p); \
+ (variable= *variable##p); \
+ variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+ (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHelem_">-</a>
+
+ FOREACHelem_( set )-
+ iterate elements in a set
+
+ declare:
+ void *elem, *elemp;
+
+ each iteration:
+ elem is set element
+ elemp is one beyond
+
+ to repeat an element:
+ elemp--; / *repeat* /
+
+ at exit:
+ elem == NULL at end of loop
+
+ example:
+ FOREACHelem_(set) {
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHset_">-</a>
+
+ FOREACHset_( set )-
+ iterate a set of sets
+
+ declare:
+ setT *set, **setp;
+
+ each iteration:
+ set is set element
+ setp is one beyond
+
+ to repeat an element:
+ setp--; / *repeat* /
+
+ at exit:
+ set == NULL at end of loop
+
+ example
+ FOREACHset_(sets) {
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------------</a><a name="SETindex_">-</a>
+
+ SETindex_( set, elem )
+ return index of elem in set
+
+ notes:
+ for use with FOREACH iteration
+
+ example:
+ i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETref_">-</a>
+
+ SETref_( elem )
+ l.h.s. for modifying the current element in a FOREACH iteration
+
+ example:
+ SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelem_">-</a>
+
+ SETelem_(set, n)
+ return the n'th element of set
+
+ notes:
+ assumes that n is valid [0..size] and that set is defined
+ use SETelemt_() for type cast
+*/
+#define SETelem_(set, n) ((set)->e[n].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelemt_">-</a>
+
+ SETelemt_(set, n, type)
+ return the n'th element of set as a type
+
+ notes:
+ assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type) ((type*)((set)->e[n].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelemaddr_">-</a>
+
+ SETelemaddr_(set, n, type)
+ return address of the n'th element of a set
+
+ notes:
+ assumes that n is valid [0..size] and set is defined
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETfirst_">-</a>
+
+ SETfirst_(set)
+ return first element of set
+
+*/
+#define SETfirst_(set) ((set)->e[0].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETfirstt_">-</a>
+
+ SETfirstt_(set, type)
+ return first element of set as a type
+
+*/
+#define SETfirstt_(set, type) ((type*)((set)->e[0].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETsecond_">-</a>
+
+ SETsecond_(set)
+ return second element of set
+
+*/
+#define SETsecond_(set) ((set)->e[1].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETsecondt_">-</a>
+
+ SETsecondt_(set, type)
+ return second element of set as a type
+*/
+#define SETsecondt_(set, type) ((type*)((set)->e[1].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETaddr_">-</a>
+
+ SETaddr_(set, type)
+ return address of set's elements
+*/
+#define SETaddr_(set,type) ((type **)(&((set)->e[0].p)))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETreturnsize_">-</a>
+
+ SETreturnsize_(set, size)
+ return size of a set
+
+ notes:
+ set must be defined
+ use qh_setsize(set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETempty_">-</a>
+
+ SETempty_(set)
+ return true (1) if set is empty
+
+ notes:
+ set may be NULL
+*/
+#define SETempty_(set) (!set || (SETfirst_(set) ? 0:1))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETtruncate_">-</a>
+
+ SETtruncate_(set)
+ return first element of set
+
+ see:
+ qh_settruncate()
+
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+ set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+void qh_setaddsorted(setT **setp, void *elem);
+void qh_setaddnth(setT **setp, int nth, void *newelem);
+void qh_setappend(setT **setp, void *elem);
+void qh_setappend_set(setT **setp, setT *setA);
+void qh_setappend2ndlast(setT **setp, void *elem);
+void qh_setcheck(setT *set, char *tname, int id);
+void qh_setcompact(setT *set);
+setT *qh_setcopy(setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(setT *set, int nth);
+void *qh_setdelnthsorted(setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate( setT *set, int elemsize);
+int qh_setequal(setT *setA, setT *setB);
+int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
+void qh_setfree(setT **set);
+void qh_setfree2( setT **setp, int elemsize);
+void qh_setfreelong(setT **set);
+int qh_setin(setT *set, void *setelem);
+int qh_setindex(setT *set, void *setelem);
+void qh_setlarger(setT **setp);
+void *qh_setlast(setT *set);
+setT *qh_setnew(int size);
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
+void qh_setprint(FILE *fp, char* string, setT *set);
+void qh_setreplace(setT *set, void *oldelem, void *newelem);
+int qh_setsize(setT *set);
+setT *qh_settemp(int setsize);
+void qh_settempfree(setT **set);
+void qh_settempfree_all(void);
+setT *qh_settemppop(void);
+void qh_settemppush(setT *set);
+void qh_settruncate (setT *set, int size);
+int qh_setunique (setT **set, void *elem);
+void qh_setzero (setT *set, int index, int size);
+
+
+#endif /* qhDEFset */
diff --git a/extern/qhull/include/qhull/stat.h b/extern/qhull/include/qhull/stat.h
new file mode 100644
index 00000000000..1dae54ed21d
--- /dev/null
+++ b/extern/qhull/include/qhull/stat.h
@@ -0,0 +1,520 @@
+ /*<html><pre> -<a href="qh-stat.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ stat.h
+ contains all statistics that are collected for qhull
+
+ see qh-stat.htm and stat.c
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ recompile qhull if you change this file
+
+ Integer statistics are Z* while real statistics are W*.
+
+ define maydebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="KEEPstatistics">-</a>
+
+ qh_KEEPstatistics
+ 0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="statistics">-</a>
+
+ Zxxx for integers, Wxxx for reals
+
+ notes:
+ be sure that all statistics are defined in stat.c
+ otherwise initialization may core dump
+ can pick up all statistics by:
+ grep '[zw].*_[(][ZW]' *.c >z.x
+ remove trailers with query">-</a>
+ remove leaders with query-replace-regexp [ ^I]+ (
+*/
+#if qh_KEEPstatistics
+enum statistics { /* alphabetical after Z/W */
+ Zacoplanar,
+ Wacoplanarmax,
+ Wacoplanartot,
+ Zangle,
+ Wangle,
+ Wanglemax,
+ Wanglemin,
+ Zangletests,
+ Wareatot,
+ Wareamax,
+ Wareamin,
+ Zavoidold,
+ Wavoidoldmax,
+ Wavoidoldtot,
+ Zback0,
+ Zbestcentrum,
+ Zbestdist,
+ Zcentrumtests,
+ Zcheckpart,
+ Zcomputefurthest,
+ Zconcave,
+ Wconcavemax,
+ Wconcavetot,
+ Zconcaveridges,
+ Zconcaveridge,
+ Zcoplanar,
+ Wcoplanarmax,
+ Wcoplanartot,
+ Zcoplanarangle,
+ Zcoplanarcentrum,
+ Zcoplanarhorizon,
+ Zcoplanarinside,
+ Zcoplanarpart,
+ Zcoplanarridges,
+ Wcpu,
+ Zcyclefacetmax,
+ Zcyclefacettot,
+ Zcyclehorizon,
+ Zcyclevertex,
+ Zdegen,
+ Wdegenmax,
+ Wdegentot,
+ Zdegenvertex,
+ Zdelfacetdup,
+ Zdelridge,
+ Zdelvertextot,
+ Zdelvertexmax,
+ Zdetsimplex,
+ Zdistcheck,
+ Zdistconvex,
+ Zdistgood,
+ Zdistio,
+ Zdistplane,
+ Zdiststat,
+ Zdistvertex,
+ Zdistzero,
+ Zdoc1,
+ Zdoc2,
+ Zdoc3,
+ Zdoc4,
+ Zdoc5,
+ Zdoc6,
+ Zdoc7,
+ Zdoc8,
+ Zdoc9,
+ Zdoc10,
+ Zdoc11,
+ Zdoc12,
+ Zdropdegen,
+ Zdropneighbor,
+ Zdupflip,
+ Zduplicate,
+ Wduplicatemax,
+ Wduplicatetot,
+ Zdupridge,
+ Zdupsame,
+ Zflipped,
+ Wflippedmax,
+ Wflippedtot,
+ Zflippedfacets,
+ Zfindbest,
+ Zfindbestmax,
+ Zfindbesttot,
+ Zfindcoplanar,
+ Zfindfail,
+ Zfindhorizon,
+ Zfindhorizonmax,
+ Zfindhorizontot,
+ Zfindjump,
+ Zfindnew,
+ Zfindnewmax,
+ Zfindnewtot,
+ Zfindnewjump,
+ Zfindnewsharp,
+ Zgauss0,
+ Zgoodfacet,
+ Zhashlookup,
+ Zhashridge,
+ Zhashridgetest,
+ Zhashtests,
+ Zinsidevisible,
+ Zintersect,
+ Zintersectfail,
+ Zintersectmax,
+ Zintersectnum,
+ Zintersecttot,
+ Zmaxneighbors,
+ Wmaxout,
+ Wmaxoutside,
+ Zmaxridges,
+ Zmaxvertex,
+ Zmaxvertices,
+ Zmaxvneighbors,
+ Zmemfacets,
+ Zmempoints,
+ Zmemridges,
+ Zmemvertices,
+ Zmergeflipdup,
+ Zmergehorizon,
+ Zmergeinittot,
+ Zmergeinitmax,
+ Zmergeinittot2,
+ Zmergeintohorizon,
+ Zmergenew,
+ Zmergesettot,
+ Zmergesetmax,
+ Zmergesettot2,
+ Zmergesimplex,
+ Zmergevertex,
+ Wmindenom,
+ Wminvertex,
+ Zminnorm,
+ Zmultiridge,
+ Znearlysingular,
+ Zneighbor,
+ Wnewbalance,
+ Wnewbalance2,
+ Znewfacettot,
+ Znewfacetmax,
+ Znewvertex,
+ Wnewvertex,
+ Wnewvertexmax,
+ Znoarea,
+ Znonsimplicial,
+ Znowsimplicial,
+ Znotgood,
+ Znotgoodnew,
+ Znotmax,
+ Znumfacets,
+ Znummergemax,
+ Znummergetot,
+ Znumneighbors,
+ Znumridges,
+ Znumvertices,
+ Znumvisibility,
+ Znumvneighbors,
+ Zonehorizon,
+ Zpartangle,
+ Zpartcoplanar,
+ Zpartflip,
+ Zparthorizon,
+ Zpartinside,
+ Zpartition,
+ Zpartitionall,
+ Zpartnear,
+ Zpbalance,
+ Wpbalance,
+ Wpbalance2,
+ Zpostfacets,
+ Zpremergetot,
+ Zprocessed,
+ Zremvertex,
+ Zremvertexdel,
+ Zrenameall,
+ Zrenamepinch,
+ Zrenameshare,
+ Zretry,
+ Wretrymax,
+ Zridge,
+ Wridge,
+ Wridgemax,
+ Zridge0,
+ Wridge0,
+ Wridge0max,
+ Zridgemid,
+ Wridgemid,
+ Wridgemidmax,
+ Zridgeok,
+ Wridgeok,
+ Wridgeokmax,
+ Zsearchpoints,
+ Zsetplane,
+ Ztestvneighbor,
+ Ztotcheck,
+ Ztothorizon,
+ Ztotmerge,
+ Ztotpartcoplanar,
+ Ztotpartition,
+ Ztotridges,
+ Ztotvertices,
+ Ztotvisible,
+ Ztricoplanar,
+ Ztricoplanarmax,
+ Ztricoplanartot,
+ Ztridegen,
+ Ztrimirror,
+ Ztrinull,
+ Wvertexmax,
+ Wvertexmin,
+ Zvertexridge,
+ Zvertexridgetot,
+ Zvertexridgemax,
+ Zvertices,
+ Zvisfacettot,
+ Zvisfacetmax,
+ Zvisvertextot,
+ Zvisvertexmax,
+ Zwidefacet,
+ Zwidevertices,
+ ZEND};
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="ZZstat">-</a>
+
+ Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+ notes:
+ be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum statistics { /* for zzdef etc. macros */
+ Zback0,
+ Zbestdist,
+ Zcentrumtests,
+ Zcheckpart,
+ Zconcaveridges,
+ Zcoplanarhorizon,
+ Zcoplanarpart,
+ Zcoplanarridges,
+ Zcyclefacettot,
+ Zcyclehorizon,
+ Zdelvertextot,
+ Zdistcheck,
+ Zdistconvex,
+ Zdistzero,
+ Zdoc1,
+ Zdoc2,
+ Zdoc3,
+ Zdoc11,
+ Zflippedfacets,
+ Zgauss0,
+ Zminnorm,
+ Zmultiridge,
+ Znearlysingular,
+ Wnewvertexmax,
+ Znumvisibility,
+ Zpartcoplanar,
+ Zpartition,
+ Zpartitionall,
+ Zprocessed,
+ Zretry,
+ Zridge,
+ Wridge,
+ Wridgemax,
+ Zridge0,
+ Wridge0,
+ Wridge0max,
+ Zridgemid,
+ Wridgemid,
+ Wridgemidmax,
+ Zridgeok,
+ Wridgeok,
+ Wridgeokmax,
+ Zsetplane,
+ Ztotmerge,
+ ZEND};
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="ztype">-</a>
+
+ ztype
+ the type of a statistic sets its initial value.
+
+ notes:
+ The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="MAYdebugx">-</a>
+
+ MAYdebugx
+ define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zdef_">-</a>
+
+ zzdef_, zdef_( type, name, doc, -1)
+ define a statistic (assumes 'qhstat.next= 0;')
+
+ zdef_( type, name, doc, count)
+ define an averaged statistic
+ printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zinc_">-</a>
+
+ zzinc_( name ), zinc_( name)
+ increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zadd_">-</a>
+
+ zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+ add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zval_">-</a>
+
+ zzval_( name ), zval_( name ), wwval_( name )
+ set or return value of a statistic
+*/
+#define zzval_(id) ((qhstat stats[id]).i)
+#define wwval_(id) ((qhstat stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qhstat stats[id]).i)
+#define wval_(id) ((qhstat stats[id]).r)
+#else
+#define zval_(id) qhstat tempi
+#define wval_(id) qhstat tempr
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zmax_">-</a>
+
+ zmax_( id, val ), wmax_( id, value )
+ maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zmin_">-</a>
+
+ zmin_( id, val ), wmin_( id, value )
+ minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat.h types ==============*/
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="intrealT">-</a>
+
+ intrealT
+ union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT; /* union of int and realT */
+union intrealT {
+ int i;
+ realT r;
+};
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="qhstat">-</a>
+
+ qhstat
+ global data structure for statistics
+
+ notes:
+ access to qh_qhstat is via the "qhstat" macro. There are two choices
+ qh_QHpointer = 1 access globals via a pointer
+ enables qh_saveqhull() and qh_restoreqhull()
+ = 0 qh_qhstat is a static data structure
+ only one instance of qhull() can be active at a time
+ default value
+ qh_QHpointer is defined in qhull.h
+
+ allocated in stat.c
+*/
+typedef struct qhstatT qhstatT;
+#if qh_QHpointer
+#define qhstat qh_qhstat->
+extern qhstatT *qh_qhstat;
+#else
+#define qhstat qh_qhstat.
+extern qhstatT qh_qhstat;
+#endif
+struct qhstatT {
+ intrealT stats[ZEND]; /* integer and real statistics */
+ unsigned char id[ZEND+10]; /* id's in print order */
+ char *doc[ZEND]; /* array of documentation strings */
+ short int count[ZEND]; /* -1 if none, else index of count to use */
+ char type[ZEND]; /* type, see ztypes above */
+ char printed[ZEND]; /* true, if statistic has been printed */
+ intrealT init[ZTYPEend]; /* initial values by types, set initstatistics */
+
+ int next; /* next index for zdef_ */
+ int precision; /* index for precision problems */
+ int vridges; /* index for Voronoi ridges */
+ int tempi;
+ realT tempr;
+};
+
+/*========== function prototypes ===========*/
+
+void qh_allstatA(void);
+void qh_allstatB(void);
+void qh_allstatC(void);
+void qh_allstatD(void);
+void qh_allstatE(void);
+void qh_allstatE2(void);
+void qh_allstatF(void);
+void qh_allstatG(void);
+void qh_allstatH(void);
+void qh_allstatI(void);
+void qh_allstatistics (void);
+void qh_collectstatistics (void);
+void qh_freestatistics (void);
+void qh_initstatistics (void);
+boolT qh_newstats (int index, int *nextindex);
+boolT qh_nostatistic (int i);
+void qh_printallstatistics (FILE *fp, char *string);
+void qh_printstatistics (FILE *fp, char *string);
+void qh_printstatlevel (FILE *fp, int id, int start);
+void qh_printstats (FILE *fp, int index, int *nextindex);
+realT qh_stddev (int num, realT tot, realT tot2, realT *ave);
+
+#endif /* qhDEFstat */
diff --git a/extern/qhull/include/qhull/user.h b/extern/qhull/include/qhull/user.h
new file mode 100644
index 00000000000..79558967a52
--- /dev/null
+++ b/extern/qhull/include/qhull/user.h
@@ -0,0 +1,762 @@
+/*<html><pre> -<a href="qh-user.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ user.h
+ user redefinable constants
+
+ see qh-user.htm. see COPYING for copyright information.
+
+ before reading any code, review qhull.h for data structure definitions and
+ the "qh" macro.
+*/
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/*============= data types and configuration macros ==========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="realT">-</a>
+
+ realT
+ set the size of floating point numbers
+
+ qh_REALdigits
+ maximimum number of significant digits
+
+ qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+ format strings for printf
+
+ qh_REALmax, qh_REALmin
+ maximum and minimum (near zero) values
+
+ qh_REALepsilon
+ machine roundoff. Maximum roundoff error for addition and multiplication.
+
+ notes:
+ Select whether to store floating point numbers in single precision (float)
+ or double precision (double).
+
+ Use 'float' to save about 8% in time and 25% in space. This is particularly
+ help if high-d where convex hulls are space limited. Using 'float' also
+ reduces the printed size of Qhull's output since numbers have 8 digits of
+ precision.
+
+ Use 'double' when greater arithmetic precision is needed. This is needed
+ for Delaunay triangulations and Voronoi diagrams when you are not merging
+ facets.
+
+ If 'double' gives insufficient precision, your data probably includes
+ degeneracies. If so you should use facet merging (done by default)
+ or exact arithmetic (see imprecision section of manual, qh-impre.htm).
+ You may also use option 'Po' to force output despite precision errors.
+
+ You may use 'long double', but many format statements need to be changed
+ and you may need a 'long double' square root routine. S. Grundmann
+ (sg@eeiwzb.et.tu-dresden.de) has done this. He reports that the code runs
+ much slower with little gain in precision.
+
+ WARNING: on some machines, int f(){realT a= REALmax;return (a == REALmax);}
+ returns False. Use (a > REALmax/2) instead of (a == REALmax).
+
+ REALfloat = 1 all numbers are 'float' type
+ = 0 all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8 /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16 /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="CPUclock">-</a>
+
+ qh_CPUclock
+ define the clock() function for reporting the total time spent by Qhull
+ returns CPU ticks as a 'long int'
+ qh_CPUclock is only used for reporting the total time spent by Qhull
+
+ qh_SECticks
+ the number of clock ticks per second
+
+ notes:
+ looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+ to define a custom clock, set qh_CLOCKtype to 0
+
+ if your system does not use clock() to return CPU ticks, replace
+ qh_CPUclock with the corresponding function. It is converted
+ to unsigned long to prevent wrap-around during long runs.
+
+
+ Set qh_CLOCKtype to
+
+ 1 for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+ Note: may fail if more than 1 hour elapsed time
+
+ 2 use qh_clock() with POSIX times() (see global.c)
+*/
+#define qh_CLOCKtype 1 /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined (CLOCKS_PER_SECOND)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined (CLOCKS_PER_SEC)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined (CLK_TCK)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock qh_clock() /* return CPU clock */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="RANDOM">-</a>
+
+ qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+ define random number generator
+
+ qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
+ qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+ Set qh_RANDOMtype (default 5) to:
+ 1 for random() with 31 bits (UCB)
+ 2 for rand() with RAND_MAX or 15 bits (system 5)
+ 3 for rand() with 31 bits (Sun)
+ 4 for lrand48() with 31 bits (Solaris)
+ 5 for qh_rand() with 31 bits (included with Qhull)
+
+ notes:
+ Random numbers are used by rbox to generate point sets. Random
+ numbers are used by Qhull to rotate the input ('QRn' option),
+ simulate a randomized algorithm ('Qr' option), and to simulate
+ roundoff errors ('Rn' option).
+
+ Random number generators differ between systems. Most systems provide
+ rand() but the period varies. The period of rand() is not critical
+ since qhull does not normally use random numbers.
+
+ The default generator is Park & Miller's minimal standard random
+ number generator [CACM 31:1195 '88]. It is included with Qhull.
+
+ If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
+ output will likely be invisible.
+*/
+#define qh_RANDOMtype 5 /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767) /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, Sun */
+#define qh_RANDOMint rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)
+#define qh_RANDOMmax ((realT)2147483646UL) /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand()
+#define qh_RANDOMseed_(seed) qh_srand(seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="ORIENTclock">-</a>
+
+ qh_ORIENTclock
+ 0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0
+
+
+/*========= performance related constants =========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="HASHfactor">-</a>
+
+ qh_HASHfactor
+ total hash slots / used hash slots. Must be at least 1.1.
+
+ notes:
+ =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="VERIFYdirect">-</a>
+
+ qh_VERIFYdirect
+ with 'Tv' verify all points against all facets if op count is smaller
+
+ notes:
+ if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INITIALsearch">-</a>
+
+ qh_INITIALsearch
+ if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INITIALmax">-</a>
+
+ qh_INITIALmax
+ if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+
+ notes:
+ from points with non-zero determinants
+ use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEdefault">-</a>
+
+ qh_JOGGLEdefault
+ default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+ notes:
+ rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+ rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+ rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+ rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+ rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+ rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+ rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+ rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+ rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+ the later have about 20 points per facet, each of which may interfere
+
+ pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEincrease">-</a>
+
+ qh_JOGGLEincrease
+ factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEretry">-</a>
+
+ qh_JOGGLEretry
+ if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+ notes:
+ try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEagain">-</a>
+
+ qh_JOGGLEagain
+ every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+ notes:
+ 1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEmaxincrease">-</a>
+
+ qh_JOGGLEmaxincrease
+ maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+ relative to qh.MAXwidth
+
+ notes:
+ qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEmaxretry">-</a>
+
+ qh_JOGGLEmaxretry
+ stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 100
+
+/*========= memory constants =========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMalign">-</a>
+
+ qh_MEMalign
+ memory alignment for qh_meminitbuffers() in global.c
+
+ notes:
+ to avoid bus errors, memory allocation must consider alignment requirements.
+ malloc() automatically takes care of alignment. Since mem.c manages
+ its own memory, we need to explicitly specify alignment in
+ qh_meminitbuffers().
+
+ A safe choice is sizeof(double). sizeof(float) may be used if doubles
+ do not occur in data structures and pointers are the same size. Be careful
+ of machines (e.g., DEC Alpha) with large pointers.
+
+ If using gcc, best alignment is
+ #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMbufsize">-</a>
+
+ qh_MEMbufsize
+ size of additional memory buffers
+
+ notes:
+ used for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMbufsize 0x10000 /* allocate 64K memory buffers */
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMinitbuf">-</a>
+
+ qh_MEMinitbuf
+ size of initial memory buffer
+
+ notes:
+ use for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMinitbuf 0x20000 /* initially allocate 128K buffer */
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INFINITE">-</a>
+
+ qh_INFINITE
+ on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE -10.101
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DEFAULTbox">-</a>
+
+ qh_DEFAULTbox
+ default box size (Geomview expects 0.5)
+*/
+#define qh_DEFAULTbox 0.5
+
+/*======= conditional compilation ============================*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="compiler">-</a>
+
+ __cplusplus
+ defined by C++ compilers
+
+ __MSC_VER
+ defined by Microsoft Visual C++
+
+ __MWERKS__ && __POWERPC__
+ defined by Metrowerks when compiling for the Power Macintosh
+
+ __STDC__
+ defined for strict ANSI C
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="COMPUTEfurthest">-</a>
+
+ qh_COMPUTEfurthest
+ compute furthest distance to an outside point instead of storing it with the facet
+ =1 to compute furthest
+
+ notes:
+ computing furthest saves memory but costs time
+ about 40% more distance tests for partitioning
+ removes facet->furthestdist
+*/
+#define qh_COMPUTEfurthest 0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="KEEPstatistics">-</a>
+
+ qh_KEEPstatistics
+ =0 removes most of statistic gathering and reporting
+
+ notes:
+ if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXoutside">-</a>
+
+ qh_MAXoutside
+ record outer plane for each facet
+ =1 to record facet->maxoutside
+
+ notes:
+ this takes a realT per facet and slightly slows down qhull
+ it produces better outer planes for geomview output
+*/
+#define qh_MAXoutside 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="NOmerge">-</a>
+
+ qh_NOmerge
+ disables facet merging if defined
+
+ notes:
+ This saves about 10% space.
+
+ Unless 'Q0'
+ qh_NOmerge sets 'QJ' to avoid precision errors
+
+ #define qh_NOmerge
+
+ see:
+ <a href="mem.h#NOmem">qh_NOmem</a> in mem.c
+
+ see user.c/user_eg.c for removing io.o
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="NOtrace">-</a>
+
+ qh_NOtrace
+ no tracing if defined
+
+ notes:
+ This saves about 5% space.
+
+ #define qh_NOtrace
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="QHpointer">-</a>
+
+ qh_QHpointer
+ access global data with pointer or static structure
+
+ qh_QHpointer = 1 access globals via a pointer to allocated memory
+ enables qh_saveqhull() and qh_restoreqhull()
+ costs about 8% in time and 2% in space
+
+ = 0 qh_qh and qh_qhstat are static data structures
+ only one instance of qhull() can be active at a time
+ default value
+
+ notes:
+ all global variables for qhull are in qh, qhmem, and qhstat
+ qh is defined in qhull.h
+ qhmem is defined in mem.h
+ qhstat is defined in stat.h
+
+ see:
+ user_eg.c for an example
+*/
+#define qh_QHpointer 0
+#if 0 /* sample code */
+ qhT *oldqhA, *oldqhB;
+
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ /* use results from first call to qh_new_qhull */
+ oldqhA= qh_save_qhull();
+ exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
+ flags, outfile, errfile);
+ /* use results from second call to qh_new_qhull */
+ oldqhB= qh_save_qhull();
+ qh_restore_qhull (&oldqhA);
+ /* use results from first call to qh_new_qhull */
+ qh_freeqhull (qh_ALL); /* frees all memory used by first call */
+ qh_restore_qhull (&oldqhB);
+ /* use results from second call to qh_new_qhull */
+ qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
+ qh_memfreeshort (&curlong, &totlong); /* frees short memory and memory allocator */
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="QUICKhelp">-</a>
+
+ qh_QUICKhelp
+ =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp 0
+
+/* ============ -merge constants- ====================
+
+ These constants effect facet merging. You probably will not need
+ to modify these. They effect the performance of facet merging.
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DIMmergeVertex">-</a>
+
+ qh_DIMmergeVertex
+ max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DIMreduceBuild">-</a>
+
+ qh_DIMreduceBuild
+ max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="BESTcentrum">-</a>
+
+ qh_BESTcentrum
+ if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+ else, qh_findbestneighbor() tests all vertices (much better merges)
+
+ qh_BESTcentrum2
+ if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="BESTnonconvex">-</a>
+
+ qh_BESTnonconvex
+ if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+
+ notes:
+ It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnewmerges">-</a>
+
+ qh_MAXnewmerges
+ if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+
+ notes:
+ It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnewcentrum">-</a>
+
+ qh_MAXnewcentrum
+ if <= dim+n vertices (n approximates the number of merges),
+ reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+
+ notes:
+ needed to reduce cost and because centrums may move too much if
+ many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="COPLANARratio">-</a>
+
+ qh_COPLANARratio
+ for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+ notes:
+ for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DISToutside">-</a>
+
+ qh_DISToutside
+ When is a point clearly outside of a facet?
+ Stops search in qh_findbestnew or qh_partitionall
+ qh_findbest uses qh.MINoutside since since it is only called if no merges.
+
+ notes:
+ 'Qf' always searches for best facet
+ if !qh.MERGING, same as qh.MINoutside.
+ if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+ [Note: Zdelvertextot occurs normally with interior points]
+ RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+ When there is a sharp edge, need to move points to a
+ clearly good facet; otherwise may be lost in another partitioning.
+ if too big then O(n^2) behavior for partitioning in cone
+ if very small then important points not processed
+ Needed in qh_partitionall for
+ RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+ Needed in qh_findbestnew for many instances of
+ RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+ fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="RATIOnearinside">-</a>
+
+ qh_RATIOnearinside
+ ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+ qh_check_maxout().
+
+ notes:
+ This is overkill since do not know the correct value.
+ It effects whether 'Qc' reports all coplanar points
+ Not used for 'd' since non-extreme points are coplanar
+*/
+#define qh_RATIOnearinside 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="SEARCHdist">-</a>
+
+ qh_SEARCHdist
+ When is a facet coplanar with the best facet?
+ qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+ (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="USEfindbestnew">-</a>
+
+ qh_USEfindbestnew
+ Always use qh_findbestnew for qh_partitionpoint, otherwise use
+ qh_findbestnew if merged new facet or sharpnewfacets.
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="WIDEcoplanar">-</a>
+
+ qh_WIDEcoplanar
+ n*MAXcoplanar or n*MINvisible for a WIDEfacet
+
+ if vertex is further than qh.WIDEfacet from the hyperplane
+ then its ridges are not counted in computing the area, and
+ the facet's centrum is frozen.
+
+ notes:
+ qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+ qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnarrow">-</a>
+
+ qh_MAXnarrow
+ max. cosine in initial hull that sets qh.NARROWhull
+
+ notes:
+ If qh.NARROWhull, the initial partition does not make
+ coplanar points. If narrow, a coplanar point can be
+ coplanar to two facets of opposite orientations and
+ distant from the exact convex hull.
+
+ Conservative estimate. Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="WARNnarrow">-</a>
+
+ qh_WARNnarrow
+ max. cosine in initial hull to warn about qh.NARROWhull
+
+ notes:
+ this is a conservative estimate.
+ Don't actually see problems until it is -1.0. See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="ZEROdelaunay">-</a>
+
+ qh_ZEROdelaunay
+ a zero Delaunay facet occurs for input sites coplanar with their convex hull
+ the last normal coefficient of a zero Delaunay facet is within
+ qh_ZEROdelaunay * qh.ANGLEround of 0
+
+ notes:
+ qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+ You can avoid zero Delaunay facets by surrounding the input with a box.
+
+ Use option 'PDk:-n' to explicitly define zero Delaunay facets
+ k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+ n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+#endif /* qh_DEFuser */
+
+
+
diff --git a/extern/qhull/make/msvc_7_0/qhull.vcproj b/extern/qhull/make/msvc_7_0/qhull.vcproj
new file mode 100644
index 00000000000..1b754d8e076
--- /dev/null
+++ b/extern/qhull/make/msvc_7_0/qhull.vcproj
@@ -0,0 +1,677 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="qhull"
+ ProjectGUID="{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\qhull"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\qhull"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\qhull\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\qhull\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\qhull\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\qhull\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\qhull.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_7\extern\qhull\include
+XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_7\extern\qhull\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\qhull\debug\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\qhull\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\qhull\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\qhull\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\debug\qhull.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_7\extern\qhull\include
+XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_7\extern\qhull\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\mtdll\qhull.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_7\extern\qhull\include
+XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_7\extern\qhull\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\qhull\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\mtdll\debug\qhull.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_7\extern\qhull\include
+XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_7\extern\qhull\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\src\geom.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\geom2.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\global.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\io.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\mem.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\merge.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\poly.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\poly2.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\qhull.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\qset.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stat.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\user.c">
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\src\geom.h">
+ </File>
+ <File
+ RelativePath="..\..\src\io.h">
+ </File>
+ <File
+ RelativePath="..\..\src\mem.h">
+ </File>
+ <File
+ RelativePath="..\..\src\merge.h">
+ </File>
+ <File
+ RelativePath="..\..\src\poly.h">
+ </File>
+ <File
+ RelativePath="..\..\src\qhull.h">
+ </File>
+ <File
+ RelativePath="..\..\src\qhull_a.h">
+ </File>
+ <File
+ RelativePath="..\..\src\qset.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stat.h">
+ </File>
+ <File
+ RelativePath="..\..\src\user.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/qhull/make/msvc_9_0/qhull.vcproj b/extern/qhull/make/msvc_9_0/qhull.vcproj
new file mode 100644
index 00000000000..fe5b3e806b6
--- /dev/null
+++ b/extern/qhull/make/msvc_9_0/qhull.vcproj
@@ -0,0 +1,877 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="EXT_qhull"
+ ProjectGUID="{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}"
+ RootNamespace="qhull"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\qhull"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\qhull"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\qhull\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\qhull\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\qhull\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\qhull\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\qhull.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\qhull\debug\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\qhull\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\qhull\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\qhull\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\debug\qhull.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\mtdll\qhull.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug\qhull.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\qhull\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\mtdll\debug\qhull.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying QHULL files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\qhull\include MKDIR ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\build\msvc_9\extern\qhull\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\src\geom.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\geom2.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\global.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\io.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\mem.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\merge.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\poly.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\poly2.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\qhull.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\qset.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stat.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\user.c"
+ >
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\src\geom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\io.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\mem.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\merge.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\poly.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\qhull.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\qhull_a.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\qset.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\stat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\user.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/qhull/src/Make-config.sh b/extern/qhull/src/Make-config.sh
new file mode 100755
index 00000000000..90bbb958599
--- /dev/null
+++ b/extern/qhull/src/Make-config.sh
@@ -0,0 +1,285 @@
+#!/bin/sh -e
+#
+# Make-config.sh
+#
+# Setup for Debian build
+#
+# Writes configure.in and Makefile.am files
+# and runs automake and autoconfig
+#
+# Use 'make dist' to build Unix distribution.
+# Use 'configure; make' to build Qhull
+#
+#note:
+# 'configure; make' does not work under cygwin.
+# src/unix.c:354: variable 'qh_qh' can't be auto-imported.
+# Please read the documentation for ld's --enable-auto-import for details.
+
+###################################################
+########### ../configure.in ######################
+###################################################
+
+echo Create ../configure.in
+cat >../configure.in <<\HERE-CONFIGURE
+dnl configure.in for the qhull package
+dnl Author: Rafael Laboissiere <rafael@debian.org>
+dnl Created: Mon Dec 3 21:36:21 CET 2001
+
+AC_INIT(src/qhull.c)
+AM_INIT_AUTOMAKE(qhull, 2002.1)
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+AC_OUTPUT([Makefile src/Makefile html/Makefile eg/Makefile])
+
+HERE-CONFIGURE
+
+###################################################
+########### ../Makefile.am #######################
+###################################################
+
+echo Create ../Makefile.am
+cat >../Makefile.am <<\HERE-TOP
+### Makefile.am for the qhull package (main)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec 3 21:36:21 CET 2001
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+
+# which:
+doc_DATA = \
+ Announce.txt \
+ COPYING.txt \
+ README.txt \
+ REGISTER.txt
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+ $(doc_DATA) \
+ File_id.diz \
+ QHULL-GO.pif
+
+### Subdirectories for Automaking
+
+SUBDIRS = src html eg
+
+HERE-TOP
+
+###################################################
+########### ../eg/Makefile.am ####################
+###################################################
+
+echo Create ../eg/Makefile.am
+cat >../eg/Makefile.am <<\HERE-AM
+### Makefile.am for the qhull package (eg)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec 3 21:36:21 CET 2001
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+examplesdir = $(docdir)/examples
+
+# which:
+examples_DATA = \
+ q_eg \
+ q_egtest \
+ q_test \
+ Qhull-go.bat \
+ q_test.bat
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = $(examples_DATA)
+
+HERE-AM
+
+###################################################
+########### ../html/Makefile.am ##################
+###################################################
+
+echo Create ../html/Makefile.am
+cat >../html/Makefile.am <<\HERE-HTML
+### Makefile.am for the qhull package (html)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec 3 21:36:21 CET 2001
+
+### Man pages (trick to get around .man extension)
+
+%.1: %.man
+ cp $< $@
+CLEANFILES = *.1
+man_MANS = rbox.1 qhull.1
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+htmldir = $(docdir)/html
+
+# which:
+html_DATA = \
+ index.htm \
+ qconvex.htm \
+ qdelau_f.htm \
+ qdelaun.htm \
+ qh--4d.gif \
+ qh--cone.gif \
+ qh--dt.gif \
+ qh--geom.gif \
+ qh--half.gif \
+ qh--rand.gif \
+ qh-eg.htm \
+ qh-faq.htm \
+ qh-get.htm \
+ qh-home.htm \
+ qh-impre.htm \
+ qh-in.htm \
+ qh-optc.htm \
+ qh-optf.htm \
+ qh-optg.htm \
+ qh-opto.htm \
+ qh-optp.htm \
+ qh-optq.htm \
+ qh-optt.htm \
+ qh-quick.htm \
+ qhalf.htm \
+ qhull.htm \
+ qvoron_f.htm \
+ qvoronoi.htm \
+ rbox.htm
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+ $(html_DATA) \
+ qhull.man \
+ qhull.txt \
+ rbox.man \
+ rbox.txt
+
+HERE-HTML
+
+###################################################
+########### ../src/Makefile.am ###################
+###################################################
+
+echo Create ../src/Makefile.am
+cat >../src/Makefile.am <<\HERE-SRC
+### Makefile.am for the qhull package (src)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec 3 21:36:21 CET 2001
+
+### Shared Library
+
+# to:
+lib_LTLIBRARIES = libqhull.la
+
+# from:
+libqhull_la_SOURCES = \
+ user.c \
+ global.c \
+ stat.c \
+ io.c \
+ geom2.c \
+ poly2.c \
+ merge.c \
+ qhull.c \
+ geom.c \
+ poly.c \
+ qset.c \
+ mem.c
+
+# how:
+libqhull_la_LDFLAGS = -version-info 0:0:0 -lm
+
+### Utility programs
+
+# to:
+bin_PROGRAMS = qhull rbox qconvex qdelaunay qvoronoi qhalf
+
+# from:
+qhull_SOURCES = unix.c
+rbox_SOURCES = rbox.c
+qconvex_SOURCES = qconvex.c
+qdelaunay_SOURCES = qdelaun.c
+qvoronoi_SOURCES = qvoronoi.c
+qhalf_SOURCES = qhalf.c
+
+# how:
+qhull_LDADD = libqhull.la
+rbox_LDADD = libqhull.la
+qconvex_LDADD = libqhull.la
+qdelaunay_LDADD = libqhull.la
+qvoronoi_LDADD = libqhull.la
+qhalf_LDADD = libqhull.la
+
+### Include files
+
+pkginclude_HEADERS = \
+ geom.h \
+ mem.h \
+ poly.h \
+ qhull_a.h \
+ stat.h \
+ io.h \
+ merge.h \
+ qhull.h \
+ qset.h \
+ user.h
+
+
+### Example programs
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+examplesdir = $(docdir)/examples
+
+# which:
+examples_DATA = \
+ user_eg.c \
+ user_eg2.c \
+ qhull_interface.cpp \
+ Makefile.txt \
+ Make-config.sh \
+ MBorland
+
+doc_DATA = Changes.txt \
+ index.htm \
+ qh-geom.htm \
+ qh-globa.htm \
+ qh-io.htm \
+ qh-mem.htm \
+ qh-merge.htm \
+ qh-poly.htm \
+ qh-qhull.htm \
+ qh-set.htm \
+ qh-stat.htm \
+ qh-user.htm
+
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+ $(doc_DATA) \
+ $(examples_DATA)
+
+HERE-SRC
+
+###################################################
+########### run automake autoconf ################
+###################################################
+
+
+echo Run automake, libtoolize, and autoconf
+cd ..; aclocal &&\
+ automake --foreign --add-missing --force-missing && \
+ libtoolize --force && \
+ autoconf
+
diff --git a/extern/qhull/src/Makefile b/extern/qhull/src/Makefile
new file mode 100644
index 00000000000..81c06758cbb
--- /dev/null
+++ b/extern/qhull/src/Makefile
@@ -0,0 +1,55 @@
+# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# vim: tabstop=8
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): GSR
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = qhull
+DIR = $(OCGDIR)/extern/$(LIBNAME)
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../include
+
+CSRCS = user.c global.c stat.c io.c geom2.c poly2.c \
+ merge.c qhull.c geom.c poly.c qset.c mem.c
+CCSRCS =
+include nan_compile.mk
+
+install: $(ALL_OR_DEBUG)
+ @[ -d $(NAN_QHULL) ] || mkdir -p $(NAN_QHULL)
+ @[ -d $(NAN_QHULL)/include/qhull ] || mkdir -p $(NAN_QHULL)/include/qhull
+ @[ -d $(NAN_QHULL)/lib/$(DEBUG_DIR) ] || mkdir -p $(NAN_QHULL)/lib/$(DEBUG_DIR)
+ @$(NANBLENDERHOME)/intern/tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)lib$(LIBNAME).a $(NAN_QHULL)/lib/$(DEBUG_DIR)
+ifeq ($(OS),darwin)
+ ranlib $(NAN_QHULL)/lib/$(DEBUG_DIR)lib$(LIBNAME).a
+endif
+ @$(NANBLENDERHOME)/intern/tools/cpifdiff.sh ../include/qhull/*.h $(NAN_QHULL)/include/qhull
+
+
diff --git a/extern/qhull/src/Makefile.txt b/extern/qhull/src/Makefile.txt
new file mode 100644
index 00000000000..e87b66b49bc
--- /dev/null
+++ b/extern/qhull/src/Makefile.txt
@@ -0,0 +1,190 @@
+# Unix Makefile for qhull and rbox
+#
+# see README.txt
+#
+# make to produce qhull qconvex qdelaunay qhalf qvoronoi rbox
+# make qvoronoi to produce qvoronoi (etc.)
+# make qhullx to produce qhull qconvex etc. w/o using libqhull.a
+# make doc to print documentation
+# make install to copy qhull, rbox, qhull.1, rbox.1 to BINDIR, MANDIR
+# make new to rebuild qhull and rbox from source
+#
+# make printall to print all files
+# make user_eg to produce user_eg
+# make user_eg2 to produce user_eg2
+# make clean to remove object files and core
+# make cleanall to remove all generated files
+#
+# PRINTMAN -- command for printing manual pages
+# PRINTC -- command for printing C files
+# BINDIR -- directory where to copy executables
+# MANDIR -- directory where to copy manual pages
+# CC -- ANSI C or C++ compiler
+# CCOPTS1 - options used to compile .c files
+# CCOPTS2 -- options used to link .o files
+#
+# CFILES -- .c files for printing
+# HFILES -- .h files for printing
+# DFILES -- documentation files
+# MFILES -- man pages and html files
+# TFILES -- .txt versions of html html files
+# FILES -- all other files
+# OBJS -- specifies the object files of libqhull.a
+#
+BINDIR = /usr/local/bin
+MANDIR = /usr/local/man/man1
+
+# if you do not have enscript, try a2ps or just use lpr. The files are text.
+PRINTMAN = enscript -2rl
+PRINTC = enscript -2r
+# PRINTMAN = lpr
+# PRINTC = lpr
+
+#for Gnu's gcc compiler -O2 for optimization, -g for debugging, -Wall for check
+#
+CC = gcc
+CCOPTS1 = -O2 -ansi
+
+# for Sun's cc compiler, -fast or O2 for optimization, -g for debugging, -Xc for ANSI
+#CC = cc
+#CCOPTS1 = -Xc -v -fast
+
+# for Silicon Graphics cc compiler, -O2 for optimization, -g for debugging
+#CC = cc
+#CCOPTS1 = -ansi -O2
+
+# for Next cc compiler with fat executable
+#CC = cc
+#CCOPTS1 = -ansi -O2 -arch m68k -arch i386 -arch hppa
+
+# for loader, ld
+CCOPTS2 = $(CCOPTS1)
+
+# OBJS in execution frequency order. CFILES after qhull.c are alphabetical
+OBJS = user.o global.o stat.o io.o geom2.o poly2.o \
+ merge.o qhull.o geom.o poly.o qset.o mem.o
+
+CFILES= unix.c qhull.c geom.c geom2.c global.c io.c mem.c merge.c poly.c \
+ poly2.c qset.c stat.c user.c qconvex.c qdelaun.c qhalf.c qvoronoi.c
+HFILES= user.h qhull.h qhull_a.h geom.h io.h mem.h merge.h poly.h qset.h stat.h
+TXTFILES= ../Announce.txt ../REGISTER.txt ../COPYING.txt ../README.txt Changes.txt
+DOCFILES= ../html/rbox.txt ../html/qhull.txt
+FILES= Makefile rbox.c user_eg.c ../eg/q_test ../eg/q_egtest ../eg/q_eg
+HTMFILES= qhull.man rbox.man qh-in.htm qh-optg.htm qh-optt.htm qh-optp.htm \
+ index.htm qh-quick.htm qh-impre.htm qh-eg.htm \
+ qh-optc.htm qh-opto.htm qh-optf.htm qh-optq.htm \
+ qh-c.htm qh-faq.htm qhull.htm qconvex.htm qdelaun.htm \
+ qh-geom.htm qh-globa.htm qh-io.htm qh-mem.htm qh-merge.htm \
+ qh-poly.htm qh-qhull.htm qh-set.htm qh-stat.htm qh-user.htm \
+ qdelau_f.htm qhalf.htm qvoronoi.htm qvoron_f.htm rbox.htm
+
+all: rbox qconvex qdelaunay qhalf qvoronoi qhull
+
+unix.o: qhull.h user.h mem.h
+qconvex.o: qhull.h user.h mem.h
+qdelaun.o: qhull.h user.h mem.h
+qhalf.o: qhull.h user.h mem.h
+qvoronoi.o: qhull.h user.h mem.h
+qhull.o: $(HFILES)
+geom.o: $(HFILES)
+geom2.o: $(HFILES)
+global.o: $(HFILES)
+io.o: $(HFILES)
+mem.o: mem.h
+merge.o: $(HFILES)
+poly.o: $(HFILES)
+poly2.o: $(HFILES)
+qset.o: qset.h mem.h
+stat.o: $(HFILES)
+user.o: $(HFILES)
+
+.c.o:
+ $(CC) -c $(CCOPTS1) $<
+
+clean:
+ rm -f *.o ../core qconvex qdelaunay qhalf qvoronoi qhull libqhull.a \
+ *.exe
+
+cleanall: clean
+ rm -f *~ ../rbox ../qhull ../qhalf ../qconvex ../qdelaunay ../qhalf\
+ ../qvoronoi ../user_eg ../user_eg2 ../*.exe >/dev/null
+
+doc:
+ $(PRINTMAN) $(TXTFILES) $(DOCFILES)
+
+install: all
+ cp ../qconvex $(BINDIR)/qconvex
+ cp ../qdelaunay $(BINDIR)/qdelaunay
+ cp ../qhalf $(BINDIR)/qhalf
+ cp ../qhull $(BINDIR)/qhull
+ cp ../qvoronoi $(BINDIR)/qvoronoi
+ cp ../rbox $(BINDIR)/rbox
+ cp ../html/qhull.man $(MANDIR)/qhull.1
+ cp ../html/rbox.man $(MANDIR)/rbox.1
+
+new: cleanall all
+
+printall: doc printh printc printf
+
+printh:
+ $(PRINTC) $(HFILES)
+
+printc:
+ $(PRINTC) $(CFILES)
+
+printf:
+ $(PRINTC) $(FILES)
+
+libqhull.a: $(OBJS)
+ @echo if 'ar' or 'ranlib' fails, try 'make qhullx'
+ ar r libqhull.a $(OBJS)
+ @echo the next line may need to be removed.
+ -test -x /bin/ranlib -o -x /usr/bin/ranlib && ranlib libqhull.a
+
+# don't use ../qconvex. Does not work on Red Hat Linux
+qconvex: qconvex.o libqhull.a
+ $(CC) -o qconvex $(CCOPTS2) qconvex.o -L. -lqhull -lm
+ cp qconvex ..
+
+qdelaunay: qdelaun.o libqhull.a
+ $(CC) -o qdelaunay $(CCOPTS2) qdelaun.o -L. -lqhull -lm
+ cp qdelaunay ..
+
+qhalf: qhalf.o libqhull.a
+ $(CC) -o qhalf $(CCOPTS2) qhalf.o -L. -lqhull -lm
+ cp qhalf ..
+
+qvoronoi: qvoronoi.o libqhull.a
+ $(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o -L. -lqhull -lm
+ cp qvoronoi ..
+
+qhull: unix.o libqhull.a
+ $(CC) -o qhull $(CCOPTS2) unix.o -L. -lqhull -lm
+ cp qhull ..
+ -chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
+ -cd ..; ./rbox D4 | ./qhull
+
+# compile qhull without using libqhull.a
+qhullx: qconvex.o qdelaun.o qhalf.o qvoronoi.o unix.o $(OBJS)
+ $(CC) -o qconvex $(CCOPTS2) qconvex.o $(OBJS) -lm
+ $(CC) -o qdelaunay $(CCOPTS2) qdelaun.o $(OBJS) -lm
+ $(CC) -o qhalf $(CCOPTS2) qhalf.o $(OBJS) -lm
+ $(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o $(OBJS) -lm
+ $(CC) -o qhull $(CCOPTS2) unix.o $(OBJS) -lm
+ cp qconvex qdelaunay qhalf qvoronoi qhull ..
+ -chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
+ -cd ..; ./rbox D4 | ./qhull
+
+rbox: rbox.o
+ $(CC) -o rbox rbox.o $(CCOPTS2) -lm
+ cp rbox ..
+
+user_eg: user_eg.o libqhull.a
+ $(CC) -o user_eg $(CCOPTS2) user_eg.o -L. -lqhull -lm
+ cp user_eg ..
+
+user_eg2: user_eg2.o libqhull.a
+ $(CC) -o user_eg2 $(CCOPTS2) user_eg2.o -L. -lqhull -lm
+ cp user_eg2 ..
+
+# end of Makefile
diff --git a/extern/qhull/src/geom.c b/extern/qhull/src/geom.c
new file mode 100644
index 00000000000..ca4bcaf2541
--- /dev/null
+++ b/extern/qhull/src/geom.c
@@ -0,0 +1,1230 @@
+/*<html><pre> -<a href="qh-geom.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ geom.c
+ geometric routines of qhull
+
+ see qh-geom.htm and geom.h
+
+ copyright (c) 1993-2002 The Geometry Center
+
+ infrequent code goes into geom2.c
+*/
+
+#include "qhull_a.h"
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="distplane">-</a>
+
+ qh_distplane( point, facet, dist )
+ return distance from point to facet
+
+ returns:
+ dist
+ if qh.RANDOMdist, joggles result
+
+ notes:
+ dist > 0 if point is above facet (i.e., outside)
+ does not error (for sortfacets)
+
+ see:
+ qh_distnorm in geom2.c
+*/
+void qh_distplane (pointT *point, facetT *facet, realT *dist) {
+ coordT *normal= facet->normal, *coordp, randr;
+ int k;
+
+ switch(qh hull_dim){
+ case 2:
+ *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
+ break;
+ case 3:
+ *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
+ break;
+ case 4:
+ *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
+ break;
+ case 5:
+ *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
+ break;
+ case 6:
+ *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
+ break;
+ case 7:
+ *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
+ break;
+ case 8:
+ *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
+ break;
+ default:
+ *dist= facet->offset;
+ coordp= point;
+ for (k= qh hull_dim; k--; )
+ *dist += *coordp++ * *normal++;
+ break;
+ }
+ zinc_(Zdistplane);
+ if (!qh RANDOMdist && qh IStracing < 4)
+ return;
+ if (qh RANDOMdist) {
+ randr= qh_RANDOMint;
+ *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
+ qh RANDOMfactor * qh MAXabs_coord;
+ }
+ if (qh IStracing >= 4) {
+ fprintf (qh ferr, "qh_distplane: ");
+ fprintf (qh ferr, qh_REAL_1, *dist);
+ fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
+ }
+ return;
+} /* distplane */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="findbest">-</a>
+
+ qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
+ find facet that is furthest below a point
+ for upperDelaunay facets
+ returns facet only if !qh_NOupper and clearly above
+
+ input:
+ starts search at 'startfacet' (can not be flipped)
+ if !bestoutside (qh_ALL), stops at qh.MINoutside
+
+ returns:
+ best facet (reports error if NULL)
+ early out if isoutside defined and bestdist > qh.MINoutside
+ dist is distance to facet
+ isoutside is true if point is outside of facet
+ numpart counts the number of distance tests
+
+ see also:
+ qh_findbestnew()
+
+ notes:
+ If merging (testhorizon), searches horizon facets of coplanar best facets because
+ after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
+ avoid calls to distplane, function calls, and real number operations.
+ caller traces result
+ Optimized for outside points. Tried recording a search set for qh_findhorizon.
+ Made code more complicated.
+
+ when called by qh_partitionvisible():
+ indicated by qh_ISnewfacets
+ qh.newfacet_list is list of simplicial, new facets
+ qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
+ qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
+
+ when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
+ qh_check_bestdist(), qh_addpoint()
+ indicated by !qh_ISnewfacets
+ returns best facet in neighborhood of given facet
+ this is best facet overall if dist > - qh.MAXcoplanar
+ or hull has at least a "spherical" curvature
+
+ design:
+ initialize and test for early exit
+ repeat while there are better facets
+ for each neighbor of facet
+ exit if outside facet found
+ test for better facet
+ if point is inside and partitioning
+ test for new facets with a "sharp" intersection
+ if so, future calls go to qh_findbestnew()
+ test horizon facets
+*/
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+ boolT bestoutside, boolT isnewfacets, boolT noupper,
+ realT *dist, boolT *isoutside, int *numpart) {
+ realT bestdist= -REALmax/2 /* avoid underflow */;
+ facetT *facet, *neighbor, **neighborp, *bestfacet= NULL;
+ /* facetT *bestfacet_all= startfacet; */
+ int oldtrace= qh IStracing;
+ unsigned int visitid= ++qh visit_id;
+ int numpartnew=0;
+ boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+ zinc_(Zfindbest);
+ if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+ if (qh TRACElevel > qh IStracing)
+ qh IStracing= qh TRACElevel;
+ fprintf (qh ferr, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
+ qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
+ fprintf(qh ferr, " testhorizon? %d noupper? %d", testhorizon, noupper);
+ fprintf (qh ferr, " Last point added was p%d.", qh furthest_id);
+ fprintf(qh ferr, " Last merge was #%d. max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
+ }
+ if (isoutside)
+ *isoutside= True;
+ if (!startfacet->flipped) { /* test startfacet */
+ *numpart= 1;
+ qh_distplane (point, startfacet, dist); /* this code is duplicated below */
+ if (!bestoutside && *dist >= qh MINoutside
+ && (!startfacet->upperdelaunay || !noupper)) {
+ bestfacet= startfacet;
+ goto LABELreturn_best;
+ }
+ bestdist= *dist;
+ if (!startfacet->upperdelaunay) {
+ bestfacet= startfacet;
+ }
+ }else
+ *numpart= 0;
+ startfacet->visitid= visitid;
+ facet= startfacet;
+ while (facet) {
+ trace4((qh ferr, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
+ facet->id, bestdist, getid_(bestfacet)));
+ FOREACHneighbor_(facet) {
+ if (!neighbor->newfacet && isnewfacets)
+ continue;
+ if (neighbor->visitid == visitid)
+ continue;
+ neighbor->visitid= visitid;
+ if (!neighbor->flipped) { /* code duplicated above */
+ (*numpart)++;
+ qh_distplane (point, neighbor, dist);
+ if (*dist > bestdist) {
+ if (!bestoutside && *dist >= qh MINoutside
+ && (!neighbor->upperdelaunay || !noupper)) {
+ bestfacet= neighbor;
+ goto LABELreturn_best;
+ }
+ if (!neighbor->upperdelaunay) {
+ bestfacet= neighbor;
+ bestdist= *dist;
+ }
+ break; /* switch to neighor */
+ } /* end of *dist>bestdist */
+ } /* end of !flipped */
+ } /* end of FOREACHneighbor */
+ facet= neighbor; /* non-NULL only if *dist>bestdist */
+ } /* end of while facet (directed search) */
+ if (isnewfacets) {
+ if (!bestfacet) {
+ bestdist= -REALmax/2;
+ bestfacet= qh_findbestnew (point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
+ testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+ }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
+ if (qh_sharpnewfacets()) {
+ /* seldom used, qh_findbestnew will retest all facets */
+ zinc_(Zfindnewsharp);
+ bestfacet= qh_findbestnew (point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
+ testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+ qh findbestnew= True;
+ }else
+ qh findbest_notsharp= True;
+ }
+ }
+ if (!bestfacet) {
+ fprintf(qh ferr, "\n\
+qh_findbest: all neighbors of facet %d are flipped or upper Delaunay.\n\
+Please report this error to qhull_bug@geom.umn.edu with the input and all of the output.\n",
+ startfacet->id);
+ qh_errexit (qh_ERRqhull, startfacet, NULL);
+ }
+ if (testhorizon)
+ bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
+ *dist= bestdist;
+ if (isoutside && bestdist < qh MINoutside)
+ *isoutside= False;
+LABELreturn_best:
+ zadd_(Zfindbesttot, *numpart);
+ zmax_(Zfindbestmax, *numpart);
+ (*numpart) += numpartnew;
+ qh IStracing= oldtrace;
+ return bestfacet;
+} /* findbest */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="findbesthorizon">-</a>
+
+ qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
+ search coplanar and better horizon facets from startfacet/bestdist
+ ischeckmax turns off statistics and minsearch update
+ all arguments must be initialized
+ returns (ischeckmax):
+ best facet
+ returns (!ischeckmax):
+ best facet that is not upperdelaunay
+ allows upperdelaunay that is clearly outside
+ returns:
+ bestdist is distance to bestfacet
+ numpart -- updates number of distance tests
+
+ notes:
+ no early out -- use qh_findbest() or qh_findbestnew()
+ Searches coplanar or better horizon facets
+
+ when called by qh_check_maxout() (qh_IScheckmax)
+ startfacet must be closest to the point
+ Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
+ even though other facets are below the point.
+ updates facet->maxoutside for good, visited facets
+ may return NULL
+
+ searchdist is qh.max_outside + 2 * DISTround
+ + max( MINvisible('Vn'), MAXcoplanar('Un'));
+ This setting is a guess. It must be at least max_outside + 2*DISTround
+ because a facet may have a geometric neighbor across a vertex
+
+ design:
+ for each horizon facet of coplanar best facets
+ continue if clearly inside
+ unless upperdelaunay or clearly outside
+ update best facet
+*/
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
+ facetT *bestfacet= startfacet;
+ realT dist;
+ facetT *neighbor, **neighborp, *facet;
+ facetT *nextfacet= NULL; /* optimize last facet of coplanarset */
+ int numpartinit= *numpart, coplanarset_size;
+ unsigned int visitid= ++qh visit_id;
+ boolT newbest= False; /* for tracing */
+ realT minsearch, searchdist; /* skip facets that are too far from point */
+
+ if (!ischeckmax) {
+ zinc_(Zfindhorizon);
+ }else {
+#if qh_MAXoutside
+ if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
+ startfacet->maxoutside= *bestdist;
+#endif
+ }
+ searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
+ minsearch= *bestdist - searchdist;
+ if (ischeckmax) {
+ /* Always check coplanar facets. Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
+ minimize_(minsearch, -searchdist);
+ }
+ coplanarset_size= 0;
+ facet= startfacet;
+ while (True) {
+ trace4((qh ferr, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
+ facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
+ minsearch, searchdist));
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid == visitid)
+ continue;
+ neighbor->visitid= visitid;
+ if (!neighbor->flipped) {
+ qh_distplane (point, neighbor, &dist);
+ (*numpart)++;
+ if (dist > *bestdist) {
+ if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
+ bestfacet= neighbor;
+ *bestdist= dist;
+ newbest= True;
+ if (!ischeckmax) {
+ minsearch= dist - searchdist;
+ if (dist > *bestdist + searchdist) {
+ zinc_(Zfindjump); /* everything in qh.coplanarset at least searchdist below */
+ coplanarset_size= 0;
+ }
+ }
+ }
+ }else if (dist < minsearch)
+ continue; /* if ischeckmax, dist can't be positive */
+#if qh_MAXoutside
+ if (ischeckmax && dist > neighbor->maxoutside)
+ neighbor->maxoutside= dist;
+#endif
+ } /* end of !flipped */
+ if (nextfacet) {
+ if (!coplanarset_size++) {
+ SETfirst_(qh coplanarset)= nextfacet;
+ SETtruncate_(qh coplanarset, 1);
+ }else
+ qh_setappend (&qh coplanarset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
+ and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv */
+ }
+ nextfacet= neighbor;
+ } /* end of EACHneighbor */
+ facet= nextfacet;
+ if (facet)
+ nextfacet= NULL;
+ else if (!coplanarset_size)
+ break;
+ else if (!--coplanarset_size) {
+ facet= SETfirst_(qh coplanarset);
+ SETtruncate_(qh coplanarset, 0);
+ }else
+ facet= (facetT*)qh_setdellast (qh coplanarset);
+ } /* while True, for each facet in qh.coplanarset */
+ if (!ischeckmax) {
+ zadd_(Zfindhorizontot, *numpart - numpartinit);
+ zmax_(Zfindhorizonmax, *numpart - numpartinit);
+ if (newbest)
+ zinc_(Zparthorizon);
+ }
+ trace4((qh ferr, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
+ return bestfacet;
+} /* findbesthorizon */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="findbestnew">-</a>
+
+ qh_findbestnew( point, startfacet, dist, isoutside, numpart )
+ find best newfacet for point
+ searches all of qh.newfacet_list starting at startfacet
+ searches horizon facets of coplanar best newfacets
+ searches all facets if startfacet == qh.facet_list
+ returns:
+ best new or horizon facet that is not upperdelaunay
+ early out if isoutside and not 'Qf'
+ dist is distance to facet
+ isoutside is true if point is outside of facet
+ numpart is number of distance tests
+
+ notes:
+ Always used for merged new facets (see qh_USEfindbestnew)
+ Avoids upperdelaunay facet unless (isoutside and outside)
+
+ Uses qh.visit_id, qh.coplanarset.
+ If share visit_id with qh_findbest, coplanarset is incorrect.
+
+ If merging (testhorizon), searches horizon facets of coplanar best facets because
+ a point maybe coplanar to the bestfacet, below its horizon facet,
+ and above a horizon facet of a coplanar newfacet. For example,
+ rbox 1000 s Z1 G1e-13 | qhull
+ rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
+
+ qh_findbestnew() used if
+ qh_sharpnewfacets -- newfacets contains a sharp angle
+ if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
+
+ see also:
+ qh_partitionall() and qh_findbest()
+
+ design:
+ for each new facet starting from startfacet
+ test distance from point to facet
+ return facet if clearly outside
+ unless upperdelaunay and a lowerdelaunay exists
+ update best facet
+ test horizon facets
+*/
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+ realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
+ realT bestdist= -REALmax/2; /*, minsearch= -REALmax/2;*/
+ facetT *bestfacet= NULL, *facet;
+ int oldtrace= qh IStracing, i;
+ unsigned int visitid= ++qh visit_id;
+ realT distoutside= 0.0;
+ boolT isdistoutside; /* True if distoutside is defined */
+ boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+ if (!startfacet) {
+ if (qh MERGING)
+ fprintf(qh ferr, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets. Can not continue.\n");
+ else
+ fprintf(qh ferr, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
+ qh furthest_id);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ zinc_(Zfindnew);
+ if (qh BESToutside || bestoutside)
+ isdistoutside= False;
+ else {
+ isdistoutside= True;
+ distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+ }
+ if (isoutside)
+ *isoutside= True;
+ *numpart= 0;
+ if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+ if (qh TRACElevel > qh IStracing)
+ qh IStracing= qh TRACElevel;
+ fprintf(qh ferr, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
+ qh_pointid(point), startfacet->id, isdistoutside, distoutside);
+ fprintf(qh ferr, " Last point added p%d visitid %d.", qh furthest_id, visitid);
+ fprintf(qh ferr, " Last merge was #%d.\n", zzval_(Ztotmerge));
+ }
+ /* visit all new facets starting with startfacet, maybe qh facet_list */
+ for (i= 0, facet= startfacet; i < 2; i++, facet= qh newfacet_list) {
+ FORALLfacet_(facet) {
+ if (facet == startfacet && i)
+ break;
+ facet->visitid= visitid;
+ if (!facet->flipped) {
+ qh_distplane (point, facet, dist);
+ (*numpart)++;
+ if (*dist > bestdist) {
+ if (!facet->upperdelaunay || *dist >= qh MINoutside) {
+ bestfacet= facet;
+ if (isdistoutside && *dist >= distoutside)
+ goto LABELreturn_bestnew;
+ bestdist= *dist;
+ }
+ }
+ } /* end of !flipped */
+ } /* FORALLfacet from startfacet or qh newfacet_list */
+ }
+ if (testhorizon || !bestfacet)
+ bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
+ !qh_NOupper, &bestdist, numpart);
+ *dist= bestdist;
+ if (isoutside && *dist < qh MINoutside)
+ *isoutside= False;
+LABELreturn_bestnew:
+ zadd_(Zfindnewtot, *numpart);
+ zmax_(Zfindnewmax, *numpart);
+ trace4((qh ferr, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
+ qh IStracing= oldtrace;
+ return bestfacet;
+} /* findbestnew */
+
+/* ============ hyperplane functions -- keep code together [?] ============ */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="backnormal">-</a>
+
+ qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
+ given an upper-triangular rows array and a sign,
+ solve for normal equation x using back substitution over rows U
+
+ returns:
+ normal= x
+
+ if will not be able to divzero() when normalized (qh.MINdenom_2 and qh.MINdenom_1_2),
+ if fails on last row
+ this means that the hyperplane intersects [0,..,1]
+ sets last coordinate of normal to sign
+ otherwise
+ sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
+ sets nearzero
+
+ notes:
+ assumes numrow == numcol-1
+
+ see Golub & van Loan 4.4-9 for back substitution
+
+ solves Ux=b where Ax=b and PA=LU
+ b= [0,...,0,sign or 0] (sign is either -1 or +1)
+ last row of A= [0,...,0,1]
+
+ 1) Ly=Pb == y=b since P only permutes the 0's of b
+
+ design:
+ for each row from end
+ perform back substitution
+ if near zero
+ use qh_divzero for division
+ if zero divide and not last row
+ set tail of normal to 0
+*/
+void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
+ coordT *normal, boolT *nearzero) {
+ int i, j;
+ coordT *normalp, *normal_tail, *ai, *ak;
+ realT diagonal;
+ boolT waszero;
+ int zerocol= -1;
+
+ normalp= normal + numcol - 1;
+ *normalp--= (sign ? -1.0 : 1.0);
+ for(i= numrow; i--; ) {
+ *normalp= 0.0;
+ ai= rows[i] + i + 1;
+ ak= normalp+1;
+ for(j= i+1; j < numcol; j++)
+ *normalp -= *ai++ * *ak++;
+ diagonal= (rows[i])[i];
+ if (fabs_(diagonal) > qh MINdenom_2)
+ *(normalp--) /= diagonal;
+ else {
+ waszero= False;
+ *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
+ if (waszero) {
+ zerocol= i;
+ *(normalp--)= (sign ? -1.0 : 1.0);
+ for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
+ *normal_tail= 0.0;
+ }else
+ normalp--;
+ }
+ }
+ if (zerocol != -1) {
+ zzinc_(Zback0);
+ *nearzero= True;
+ trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
+ qh_precision ("zero diagonal on back substitution");
+ }
+} /* backnormal */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="gausselim">-</a>
+
+ qh_gausselim( rows, numrow, numcol, sign )
+ Gaussian elimination with partial pivoting
+
+ returns:
+ rows is upper triangular (includes row exchanges)
+ flips sign for each row exchange
+ sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
+
+ notes:
+ if nearzero, the determinant's sign may be incorrect.
+ assumes numrow <= numcol
+
+ design:
+ for each row
+ determine pivot and exchange rows if necessary
+ test for near zero
+ perform gaussian elimination step
+*/
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
+ realT *ai, *ak, *rowp, *pivotrow;
+ realT n, pivot, pivot_abs= 0.0, temp;
+ int i, j, k, pivoti, flip=0;
+
+ *nearzero= False;
+ for(k= 0; k < numrow; k++) {
+ pivot_abs= fabs_((rows[k])[k]);
+ pivoti= k;
+ for(i= k+1; i < numrow; i++) {
+ if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
+ pivot_abs= temp;
+ pivoti= i;
+ }
+ }
+ if (pivoti != k) {
+ rowp= rows[pivoti];
+ rows[pivoti]= rows[k];
+ rows[k]= rowp;
+ *sign ^= 1;
+ flip ^= 1;
+ }
+ if (pivot_abs <= qh NEARzero[k]) {
+ *nearzero= True;
+ if (pivot_abs == 0.0) { /* remainder of column == 0 */
+ if (qh IStracing >= 4) {
+ fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
+ qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
+ }
+ zzinc_(Zgauss0);
+ qh_precision ("zero pivot for Gaussian elimination");
+ goto LABELnextcol;
+ }
+ }
+ pivotrow= rows[k] + k;
+ pivot= *pivotrow++; /* signed value of pivot, and remainder of row */
+ for(i= k+1; i < numrow; i++) {
+ ai= rows[i] + k;
+ ak= pivotrow;
+ n= (*ai++)/pivot; /* divzero() not needed since |pivot| >= |*ai| */
+ for(j= numcol - (k+1); j--; )
+ *ai++ -= n * *ak++;
+ }
+ LABELnextcol:
+ ;
+ }
+ wmin_(Wmindenom, pivot_abs); /* last pivot element */
+ if (qh IStracing >= 5)
+ qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
+} /* gausselim */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="getangle">-</a>
+
+ qh_getangle( vect1, vect2 )
+ returns the dot product of two vectors
+ if qh.RANDOMdist, joggles result
+
+ notes:
+ the angle may be > 1.0 or < -1.0 because of roundoff errors
+
+*/
+realT qh_getangle(pointT *vect1, pointT *vect2) {
+ realT angle= 0, randr;
+ int k;
+
+ for(k= qh hull_dim; k--; )
+ angle += *vect1++ * *vect2++;
+ if (qh RANDOMdist) {
+ randr= qh_RANDOMint;
+ angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
+ qh RANDOMfactor;
+ }
+ trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
+ return(angle);
+} /* getangle */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="getcenter">-</a>
+
+ qh_getcenter( vertices )
+ returns arithmetic center of a set of vertices as a new point
+
+ notes:
+ allocates point array for center
+*/
+pointT *qh_getcenter(setT *vertices) {
+ int k;
+ pointT *center, *coord;
+ vertexT *vertex, **vertexp;
+ int count= qh_setsize(vertices);
+
+ if (count < 2) {
+ fprintf (qh ferr, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ center= (pointT *)qh_memalloc(qh normal_size);
+ for (k=0; k < qh hull_dim; k++) {
+ coord= center+k;
+ *coord= 0.0;
+ FOREACHvertex_(vertices)
+ *coord += vertex->point[k];
+ *coord /= count;
+ }
+ return(center);
+} /* getcenter */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="getcentrum">-</a>
+
+ qh_getcentrum( facet )
+ returns the centrum for a facet as a new point
+
+ notes:
+ allocates the centrum
+*/
+pointT *qh_getcentrum(facetT *facet) {
+ realT dist;
+ pointT *centrum, *point;
+
+ point= qh_getcenter(facet->vertices);
+ zzinc_(Zcentrumtests);
+ qh_distplane (point, facet, &dist);
+ centrum= qh_projectpoint(point, facet, dist);
+ qh_memfree(point, qh normal_size);
+ trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
+ facet->id, qh_setsize(facet->vertices), dist));
+ return centrum;
+} /* getcentrum */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="getdistance">-</a>
+
+ qh_getdistance( facet, neighbor, mindist, maxdist )
+ returns the maxdist and mindist distance of any vertex from neighbor
+
+ returns:
+ the max absolute value
+
+ design:
+ for each vertex of facet that is not in neighbor
+ test the distance from vertex to neighbor
+*/
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
+ vertexT *vertex, **vertexp;
+ realT dist, maxd, mind;
+
+ FOREACHvertex_(facet->vertices)
+ vertex->seen= False;
+ FOREACHvertex_(neighbor->vertices)
+ vertex->seen= True;
+ mind= 0.0;
+ maxd= 0.0;
+ FOREACHvertex_(facet->vertices) {
+ if (!vertex->seen) {
+ zzinc_(Zbestdist);
+ qh_distplane(vertex->point, neighbor, &dist);
+ if (dist < mind)
+ mind= dist;
+ else if (dist > maxd)
+ maxd= dist;
+ }
+ }
+ *mindist= mind;
+ *maxdist= maxd;
+ mind= -mind;
+ if (maxd > mind)
+ return maxd;
+ else
+ return mind;
+} /* getdistance */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="normalize">-</a>
+
+ qh_normalize( normal, dim, toporient )
+ normalize a vector and report if too small
+ does not use min norm
+
+ see:
+ qh_normalize2
+*/
+void qh_normalize (coordT *normal, int dim, boolT toporient) {
+ qh_normalize2( normal, dim, toporient, NULL, NULL);
+} /* normalize */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="normalize2">-</a>
+
+ qh_normalize2( normal, dim, toporient, minnorm, ismin )
+ normalize a vector and report if too small
+ qh.MINdenom/MINdenom1 are the upper limits for divide overflow
+
+ returns:
+ normalized vector
+ flips sign if !toporient
+ if minnorm non-NULL,
+ sets ismin if normal < minnorm
+
+ notes:
+ if zero norm
+ sets all elements to sqrt(1.0/dim)
+ if divide by zero (divzero ())
+ sets largest element to +/-1
+ bumps Znearlysingular
+
+ design:
+ computes norm
+ test for minnorm
+ if not near zero
+ normalizes normal
+ else if zero norm
+ sets normal to standard value
+ else
+ uses qh_divzero to normalize
+ if nearzero
+ sets norm to direction of maximum value
+*/
+void qh_normalize2 (coordT *normal, int dim, boolT toporient,
+ realT *minnorm, boolT *ismin) {
+ int k;
+ realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
+ boolT zerodiv;
+
+ norm1= normal+1;
+ norm2= normal+2;
+ norm3= normal+3;
+ if (dim == 2)
+ norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
+ else if (dim == 3)
+ norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
+ else if (dim == 4) {
+ norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+ + (*norm3)*(*norm3));
+ }else if (dim > 4) {
+ norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+ + (*norm3)*(*norm3);
+ for (k= dim-4, colp= normal+4; k--; colp++)
+ norm += (*colp) * (*colp);
+ norm= sqrt(norm);
+ }
+ if (minnorm) {
+ if (norm < *minnorm)
+ *ismin= True;
+ else
+ *ismin= False;
+ }
+ wmin_(Wmindenom, norm);
+ if (norm > qh MINdenom) {
+ if (!toporient)
+ norm= -norm;
+ *normal /= norm;
+ *norm1 /= norm;
+ if (dim == 2)
+ ; /* all done */
+ else if (dim == 3)
+ *norm2 /= norm;
+ else if (dim == 4) {
+ *norm2 /= norm;
+ *norm3 /= norm;
+ }else if (dim >4) {
+ *norm2 /= norm;
+ *norm3 /= norm;
+ for (k= dim-4, colp= normal+4; k--; )
+ *colp++ /= norm;
+ }
+ }else if (norm == 0.0) {
+ temp= sqrt (1.0/dim);
+ for (k= dim, colp= normal; k--; )
+ *colp++ = temp;
+ }else {
+ if (!toporient)
+ norm= -norm;
+ for (k= dim, colp= normal; k--; colp++) { /* k used below */
+ temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
+ if (!zerodiv)
+ *colp= temp;
+ else {
+ maxp= qh_maxabsval(normal, dim);
+ temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
+ for (k= dim, colp= normal; k--; colp++)
+ *colp= 0.0;
+ *maxp= temp;
+ zzinc_(Znearlysingular);
+ trace0((qh ferr, "qh_normalize: norm=%2.2g too small during p%d\n",
+ norm, qh furthest_id));
+ return;
+ }
+ }
+ }
+} /* normalize */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="projectpoint">-</a>
+
+ qh_projectpoint( point, facet, dist )
+ project point onto a facet by dist
+
+ returns:
+ returns a new point
+
+ notes:
+ if dist= distplane(point,facet)
+ this projects point to hyperplane
+ assumes qh_memfree_() is valid for normal_size
+*/
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
+ pointT *newpoint, *np, *normal;
+ int normsize= qh normal_size,k;
+ void **freelistp; /* used !qh_NOmem */
+
+ qh_memalloc_(normsize, freelistp, newpoint, pointT);
+ np= newpoint;
+ normal= facet->normal;
+ for(k= qh hull_dim; k--; )
+ *(np++)= *point++ - dist * *normal++;
+ return(newpoint);
+} /* projectpoint */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="setfacetplane">-</a>
+
+ qh_setfacetplane( facet )
+ sets the hyperplane for a facet
+ if qh.RANDOMdist, joggles hyperplane
+
+ notes:
+ uses global buffers qh.gm_matrix and qh.gm_row
+ overwrites facet->normal if already defined
+ updates Wnewvertex if PRINTstatistics
+ sets facet->upperdelaunay if upper envelope of Delaunay triangulation
+
+ design:
+ copy vertex coordinates to qh.gm_matrix/gm_row
+ compute determinate
+ if nearzero
+ recompute determinate with gaussian elimination
+ if nearzero
+ force outside orientation by testing interior point
+*/
+void qh_setfacetplane(facetT *facet) {
+ pointT *point;
+ vertexT *vertex, **vertexp;
+ int k,i, normsize= qh normal_size, oldtrace= 0;
+ realT dist;
+ void **freelistp; /* used !qh_NOmem */
+ coordT *coord, *gmcoord;
+ pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
+ boolT nearzero= False;
+
+ zzinc_(Zsetplane);
+ if (!facet->normal)
+ qh_memalloc_(normsize, freelistp, facet->normal, coordT);
+ if (facet == qh tracefacet) {
+ oldtrace= qh IStracing;
+ qh IStracing= 5;
+ fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
+ fprintf (qh ferr, " Last point added to hull was p%d.", qh furthest_id);
+ if (zzval_(Ztotmerge))
+ fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge));
+ fprintf (qh ferr, "\n\nCurrent summary is:\n");
+ qh_printsummary (qh ferr);
+ }
+ if (qh hull_dim <= 4) {
+ i= 0;
+ if (qh RANDOMdist) {
+ gmcoord= qh gm_matrix;
+ FOREACHvertex_(facet->vertices) {
+ qh gm_row[i++]= gmcoord;
+ coord= vertex->point;
+ for (k= qh hull_dim; k--; )
+ *(gmcoord++)= *coord++ * qh_randomfactor();
+ }
+ }else {
+ FOREACHvertex_(facet->vertices)
+ qh gm_row[i++]= vertex->point;
+ }
+ qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
+ facet->normal, &facet->offset, &nearzero);
+ }
+ if (qh hull_dim > 4 || nearzero) {
+ i= 0;
+ gmcoord= qh gm_matrix;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->point != point0) {
+ qh gm_row[i++]= gmcoord;
+ coord= vertex->point;
+ point= point0;
+ for(k= qh hull_dim; k--; )
+ *(gmcoord++)= *coord++ - *point++;
+ }
+ }
+ qh gm_row[i]= gmcoord; /* for areasimplex */
+ if (qh RANDOMdist) {
+ gmcoord= qh gm_matrix;
+ for (i= qh hull_dim-1; i--; ) {
+ for (k= qh hull_dim; k--; )
+ *(gmcoord++) *= qh_randomfactor();
+ }
+ }
+ qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
+ facet->normal, &facet->offset, &nearzero);
+ if (nearzero) {
+ if (qh_orientoutside (facet)) {
+ trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
+ /* this is part of using Gaussian Elimination. For example in 5-d
+ 1 1 1 1 0
+ 1 1 1 1 1
+ 0 0 0 1 0
+ 0 1 0 0 0
+ 1 0 0 0 0
+ norm= 0.38 0.38 -0.76 0.38 0
+ has a determinate of 1, but g.e. after subtracting pt. 0 has
+ 0's in the diagonal, even with full pivoting. It does work
+ if you subtract pt. 4 instead. */
+ }
+ }
+ }
+ facet->upperdelaunay= False;
+ if (qh DELAUNAY) {
+ if (qh UPPERdelaunay) { /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
+ if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
+ facet->upperdelaunay= True;
+ }else {
+ if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
+ facet->upperdelaunay= True;
+ }
+ }
+ if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->point != point0) {
+ boolT istrace= False;
+ zinc_(Zdiststat);
+ qh_distplane(vertex->point, facet, &dist);
+ dist= fabs_(dist);
+ zinc_(Znewvertex);
+ wadd_(Wnewvertex, dist);
+ if (dist > wwval_(Wnewvertexmax)) {
+ wwval_(Wnewvertexmax)= dist;
+ if (dist > qh max_outside) {
+ qh max_outside= dist; /* used by qh_maxouter() */
+ if (dist > qh TRACEdist)
+ istrace= True;
+ }
+ }else if (-dist > qh TRACEdist)
+ istrace= True;
+ if (istrace) {
+ fprintf (qh ferr, "qh_setfacetplane: ====== vertex p%d (v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
+ qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
+ qh_errprint ("DISTANT", facet, NULL, NULL, NULL);
+ }
+ }
+ }
+ qh RANDOMdist= qh old_randomdist;
+ }
+ if (qh IStracing >= 3) {
+ fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
+ facet->id, facet->offset);
+ for (k=0; k < qh hull_dim; k++)
+ fprintf (qh ferr, "%2.2g ", facet->normal[k]);
+ fprintf (qh ferr, "\n");
+ }
+ if (facet == qh tracefacet)
+ qh IStracing= oldtrace;
+} /* setfacetplane */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="sethyperplane_det">-</a>
+
+ qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
+ given dim X dim array indexed by rows[], one row per point,
+ toporient (flips all signs),
+ and point0 (any row)
+ set normalized hyperplane equation from oriented simplex
+
+ returns:
+ normal (normalized)
+ offset (places point0 on the hyperplane)
+ sets nearzero if hyperplane not through points
+
+ notes:
+ only defined for dim == 2..4
+ rows[] is not modified
+ solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
+ see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
+
+ derivation of 3-d minnorm
+ Goal: all vertices V_i within qh.one_merge of hyperplane
+ Plan: exactly translate the facet so that V_0 is the origin
+ exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
+ exactly rotate the effective perturbation to only effect n_0
+ this introduces a factor of sqrt(3)
+ n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
+ Let M_d be the max coordinate difference
+ Let M_a be the greater of M_d and the max abs. coordinate
+ Let u be machine roundoff and distround be max error for distance computation
+ The max error for n_0 is sqrt(3) u M_a M_d / norm. n_1 is approx. 1 and n_2 is approx. 0
+ The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm. Offset=0 at origin
+ Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
+ Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
+
+ derivation of 4-d minnorm
+ same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
+ [if two vertices fixed on x-axis, can rotate the other two in yzw.]
+ n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
+ [all other terms contain at least two factors nearly zero.]
+ The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
+ Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
+ Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
+*/
+void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0,
+ boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
+ realT maxround, dist;
+ int i;
+ pointT *point;
+
+
+ if (dim == 2) {
+ normal[0]= dY(1,0);
+ normal[1]= dX(0,1);
+ qh_normalize2 (normal, dim, toporient, NULL, NULL);
+ *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
+ *nearzero= False; /* since nearzero norm => incident points */
+ }else if (dim == 3) {
+ normal[0]= det2_(dY(2,0), dZ(2,0),
+ dY(1,0), dZ(1,0));
+ normal[1]= det2_(dX(1,0), dZ(1,0),
+ dX(2,0), dZ(2,0));
+ normal[2]= det2_(dX(2,0), dY(2,0),
+ dX(1,0), dY(1,0));
+ qh_normalize2 (normal, dim, toporient, NULL, NULL);
+ *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+ + point0[2]*normal[2]);
+ maxround= qh DISTround;
+ for (i=dim; i--; ) {
+ point= rows[i];
+ if (point != point0) {
+ dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+ + point[2]*normal[2]);
+ if (dist > maxround || dist < -maxround) {
+ *nearzero= True;
+ break;
+ }
+ }
+ }
+ }else if (dim == 4) {
+ normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
+ dY(1,0), dZ(1,0), dW(1,0),
+ dY(3,0), dZ(3,0), dW(3,0));
+ normal[1]= det3_(dX(2,0), dZ(2,0), dW(2,0),
+ dX(1,0), dZ(1,0), dW(1,0),
+ dX(3,0), dZ(3,0), dW(3,0));
+ normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
+ dX(1,0), dY(1,0), dW(1,0),
+ dX(3,0), dY(3,0), dW(3,0));
+ normal[3]= det3_(dX(2,0), dY(2,0), dZ(2,0),
+ dX(1,0), dY(1,0), dZ(1,0),
+ dX(3,0), dY(3,0), dZ(3,0));
+ qh_normalize2 (normal, dim, toporient, NULL, NULL);
+ *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+ + point0[2]*normal[2] + point0[3]*normal[3]);
+ maxround= qh DISTround;
+ for (i=dim; i--; ) {
+ point= rows[i];
+ if (point != point0) {
+ dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+ + point[2]*normal[2] + point[3]*normal[3]);
+ if (dist > maxround || dist < -maxround) {
+ *nearzero= True;
+ break;
+ }
+ }
+ }
+ }
+ if (*nearzero) {
+ zzinc_(Zminnorm);
+ trace0((qh ferr, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
+ zzinc_(Znearlysingular);
+ }
+} /* sethyperplane_det */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="sethyperplane_gauss">-</a>
+
+ qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
+ given (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
+ set normalized hyperplane equation from oriented simplex
+
+ returns:
+ normal (normalized)
+ offset (places point0 on the hyperplane)
+
+ notes:
+ if nearzero
+ orientation may be incorrect because of incorrect sign flips in gausselim
+ solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
+ or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
+ i.e., N is normal to the hyperplane, and the unnormalized
+ distance to [0 .. 1] is either 1 or 0
+
+ design:
+ perform gaussian elimination
+ flip sign for negative values
+ perform back substitution
+ normalize result
+ compute offset
+*/
+void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0,
+ boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
+ coordT *pointcoord, *normalcoef;
+ int k;
+ boolT sign= toporient, nearzero2= False;
+
+ qh_gausselim(rows, dim-1, dim, &sign, nearzero);
+ for(k= dim-1; k--; ) {
+ if ((rows[k])[k] < 0)
+ sign ^= 1;
+ }
+ if (*nearzero) {
+ zzinc_(Znearlysingular);
+ trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
+ qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+ }else {
+ qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+ if (nearzero2) {
+ zzinc_(Znearlysingular);
+ trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
+ }
+ }
+ if (nearzero2)
+ *nearzero= True;
+ qh_normalize2(normal, dim, True, NULL, NULL);
+ pointcoord= point0;
+ normalcoef= normal;
+ *offset= -(*pointcoord++ * *normalcoef++);
+ for(k= dim-1; k--; )
+ *offset -= *pointcoord++ * *normalcoef++;
+} /* sethyperplane_gauss */
+
+
+
diff --git a/extern/qhull/src/geom.h b/extern/qhull/src/geom.h
new file mode 100644
index 00000000000..32440cff56f
--- /dev/null
+++ b/extern/qhull/src/geom.h
@@ -0,0 +1,177 @@
+/*<html><pre> -<a href="qh-geom.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ geom.h
+ header file for geometric routines
+
+ see qh-geom.htm and geom.c
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+/* ============ -macros- ======================== */
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fabs_">-</a>
+
+ fabs_(a)
+ returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fmax_">-</a>
+
+ fmax_(a,b)
+ returns the maximum value of a and b
+*/
+#define fmax_( a,b ) ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="fmin_">-</a>
+
+ fmin_(a,b)
+ returns the minimum value of a and b
+*/
+#define fmin_( a,b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="maximize_">-</a>
+
+ maximize_(maxval, val)
+ set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="minimize_">-</a>
+
+ minimize_(minval, val)
+ set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="det2_">-</a>
+
+ det2_(a1, a2,
+ b1, b2)
+
+ compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="det3_">-</a>
+
+ det3_(a1, a2, a3,
+ b1, b2, b3,
+ c1, c2, c3)
+
+ compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+ - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="dX">-</a>
+
+ dX( p1, p2 )
+ dY( p1, p2 )
+ dZ( p1, p2 )
+
+ given two indices into rows[],
+
+ compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 ) ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 ) ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 ) ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 ) ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void qh_distplane (pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+ boolT bestoutside, boolT isnewfacets, boolT noupper,
+ realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point,
+ facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist,
+ boolT bestoutside, boolT *isoutside, int *numpart);
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void qh_normalize (coordT *normal, int dim, boolT toporient);
+void qh_normalize2 (coordT *normal, int dim, boolT toporient,
+ realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void qh_setfacetplane(facetT *newfacets);
+void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0,
+ boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0,
+ boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT qh_sharpnewfacets (void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
+void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT qh_determinant (realT **rows, int dim, boolT *nearzero);
+realT qh_detjoggle (pointT *points, int numpoints, int dimension);
+void qh_detroundoff (void);
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
+realT qh_distround (int dimension, realT maxabs, realT maxsumabs);
+realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT qh_facetarea (facetT *facet);
+realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices,
+ vertexT *notvertex, boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter (setT *vertices);
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void qh_getarea (facetT *facetlist);
+boolT qh_gram_schmidt(int dim, realT **rows);
+boolT qh_inthresholds (coordT *normal, realT *angle);
+void qh_joggleinput (void);
+realT *qh_maxabsval (realT *normal, int dim);
+setT *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT qh_maxouter (void);
+void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT qh_minabsval (realT *normal, int dim);
+int qh_mindiff (realT *vecA, realT *vecB, int dim);
+boolT qh_orientoutside (facetT *facet);
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim);
+void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
+void qh_printpoints (FILE *fp, char *string, setT *points);
+void qh_projectinput (void);
+void qh_projectpoints (signed char *project, int n, realT *points,
+ int numpoints, int dim, realT *newpoints, int newdim);
+int qh_rand( void);
+void qh_srand( int seed);
+realT qh_randomfactor (void);
+void qh_randommatrix (realT *buffer, int dim, realT **row);
+void qh_rotateinput (realT **rows);
+void qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
+void qh_scaleinput (void);
+void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+ coordT high, coordT newhigh);
+void qh_scalepoints (pointT *points, int numpoints, int dim,
+ realT *newlows, realT *newhighs);
+boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp,
+ coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center (int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/extern/qhull/src/geom2.c b/extern/qhull/src/geom2.c
new file mode 100644
index 00000000000..bd58ce1282b
--- /dev/null
+++ b/extern/qhull/src/geom2.c
@@ -0,0 +1,2160 @@
+/*<html><pre> -<a href="qh-geom.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+
+ geom2.c
+ infrequently used geometric routines of qhull
+
+ see qh-geom.htm and geom.h
+
+ copyright (c) 1993-2002 The Geometry Center
+
+ frequently used code goes into geom.c
+*/
+
+#include "qhull_a.h"
+
+/*================== functions in alphabetic order ============*/
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="copypoints">-</a>
+
+ qh_copypoints( points, numpoints, dimension)
+ return malloc'd copy of points
+*/
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension) {
+ int size;
+ coordT *newpoints;
+
+ size= numpoints * dimension * sizeof(coordT);
+ if (!(newpoints=(coordT*)malloc(size))) {
+ fprintf(qh ferr, "qhull error: insufficient memory to copy %d points\n",
+ numpoints);
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ memcpy ((char *)newpoints, (char *)points, size);
+ return newpoints;
+} /* copypoints */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="crossproduct">-</a>
+
+ qh_crossproduct( dim, vecA, vecB, vecC )
+ crossproduct of 2 dim vectors
+ C= A x B
+
+ notes:
+ from Glasner, Graphics Gems I, p. 639
+ only defined for dim==3
+*/
+void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+ if (dim == 3) {
+ vecC[0]= det2_(vecA[1], vecA[2],
+ vecB[1], vecB[2]);
+ vecC[1]= - det2_(vecA[0], vecA[2],
+ vecB[0], vecB[2]);
+ vecC[2]= det2_(vecA[0], vecA[1],
+ vecB[0], vecB[1]);
+ }
+} /* vcross */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="determinant">-</a>
+
+ qh_determinant( rows, dim, nearzero )
+ compute signed determinant of a square matrix
+ uses qh.NEARzero to test for degenerate matrices
+
+ returns:
+ determinant
+ overwrites rows and the matrix
+ if dim == 2 or 3
+ nearzero iff determinant < qh NEARzero[dim-1]
+ (not quite correct, not critical)
+ if dim >= 4
+ nearzero iff diagonal[k] < qh NEARzero[k]
+*/
+realT qh_determinant (realT **rows, int dim, boolT *nearzero) {
+ realT det=0;
+ int i;
+ boolT sign= False;
+
+ *nearzero= False;
+ if (dim < 2) {
+ fprintf (qh ferr, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }else if (dim == 2) {
+ det= det2_(rows[0][0], rows[0][1],
+ rows[1][0], rows[1][1]);
+ if (fabs_(det) < qh NEARzero[1]) /* not really correct, what should this be? */
+ *nearzero= True;
+ }else if (dim == 3) {
+ det= det3_(rows[0][0], rows[0][1], rows[0][2],
+ rows[1][0], rows[1][1], rows[1][2],
+ rows[2][0], rows[2][1], rows[2][2]);
+ if (fabs_(det) < qh NEARzero[2]) /* not really correct, what should this be? */
+ *nearzero= True;
+ }else {
+ qh_gausselim(rows, dim, dim, &sign, nearzero); /* if nearzero, diagonal still ok*/
+ det= 1.0;
+ for (i= dim; i--; )
+ det *= (rows[i])[i];
+ if (sign)
+ det= -det;
+ }
+ return det;
+} /* determinant */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="detjoggle">-</a>
+
+ qh_detjoggle( points, numpoints, dimension )
+ determine default max joggle for point array
+ as qh_distround * qh_JOGGLEdefault
+
+ returns:
+ initial value for JOGGLEmax from points and REALepsilon
+
+ notes:
+ computes DISTround since qh_maxmin not called yet
+ if qh SCALElast, last dimension will be scaled later to MAXwidth
+
+ loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle (pointT *points, int numpoints, int dimension) {
+ realT abscoord, distround, joggle, maxcoord, mincoord;
+ pointT *point, *pointtemp;
+ realT maxabs= -REALmax;
+ realT sumabs= 0;
+ realT maxwidth= 0;
+ int k;
+
+ for (k= 0; k < dimension; k++) {
+ if (qh SCALElast && k == dimension-1)
+ abscoord= maxwidth;
+ else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+ abscoord= 2 * maxabs * maxabs; /* may be low by qh hull_dim/2 */
+ else {
+ maxcoord= -REALmax;
+ mincoord= REALmax;
+ FORALLpoint_(points, numpoints) {
+ maximize_(maxcoord, point[k]);
+ minimize_(mincoord, point[k]);
+ }
+ maximize_(maxwidth, maxcoord-mincoord);
+ abscoord= fmax_(maxcoord, -mincoord);
+ }
+ sumabs += abscoord;
+ maximize_(maxabs, abscoord);
+ } /* for k */
+ distround= qh_distround (qh hull_dim, maxabs, sumabs);
+ joggle= distround * qh_JOGGLEdefault;
+ maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+ trace2((qh ferr, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+ return joggle;
+} /* detjoggle */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="detroundoff">-</a>
+
+ qh_detroundoff()
+ determine maximum roundoff errors from
+ REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
+ qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+ accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
+ qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+ qh.postmerge_centrum, qh.MINoutside,
+ qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+ returns:
+ sets qh.DISTround, etc. (see below)
+ appends precision constants to qh.qhull_options
+
+ see:
+ qh_maxmin() for qh.NEARzero
+
+ design:
+ determine qh.DISTround for distance computations
+ determine minimum denominators for qh_divzero
+ determine qh.ANGLEround for angle computations
+ adjust qh.premerge_cos,... for roundoff error
+ determine qh.ONEmerge for maximum error due to a single merge
+ determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+ qh.MINoutside, qh.WIDEfacet
+ initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff (void) {
+
+ qh_option ("_max-width", NULL, &qh MAXwidth);
+ if (!qh SETroundoff) {
+ qh DISTround= qh_distround (qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
+ if (qh RANDOMdist)
+ qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
+ qh_option ("Error-roundoff", NULL, &qh DISTround);
+ }
+ qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
+ qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ; /* if will be normalized */
+ qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
+ /* for inner product */
+ qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
+ if (qh RANDOMdist)
+ qh ANGLEround += qh RANDOMfactor;
+ if (qh premerge_cos < REALmax/2) {
+ qh premerge_cos -= qh ANGLEround;
+ if (qh RANDOMdist)
+ qh_option ("Angle-premerge-with-random", NULL, &qh premerge_cos);
+ }
+ if (qh postmerge_cos < REALmax/2) {
+ qh postmerge_cos -= qh ANGLEround;
+ if (qh RANDOMdist)
+ qh_option ("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
+ }
+ qh premerge_centrum += 2 * qh DISTround; /*2 for centrum and distplane()*/
+ qh postmerge_centrum += 2 * qh DISTround;
+ if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
+ qh_option ("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
+ if (qh RANDOMdist && qh POSTmerge)
+ qh_option ("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
+ { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+ realT maxangle= 1.0, maxrho;
+
+ minimize_(maxangle, qh premerge_cos);
+ minimize_(maxangle, qh postmerge_cos);
+ /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+ qh ONEmerge= sqrt (qh hull_dim) * qh MAXwidth *
+ sqrt (1.0 - maxangle * maxangle) + qh DISTround;
+ maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
+ maximize_(qh ONEmerge, maxrho);
+ maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
+ maximize_(qh ONEmerge, maxrho);
+ if (qh MERGING)
+ qh_option ("_one-merge", NULL, &qh ONEmerge);
+ }
+ qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
+ if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
+ realT maxdist; /* adjust qh.NEARinside for joggle */
+ qh KEEPnearinside= True;
+ maxdist= sqrt (qh hull_dim) * qh JOGGLEmax + qh DISTround;
+ maxdist= 2*maxdist; /* vertex and coplanar point can joggle in opposite directions */
+ maximize_(qh NEARinside, maxdist); /* must agree with qh_nearcoplanar() */
+ }
+ if (qh KEEPnearinside)
+ qh_option ("_near-inside", NULL, &qh NEARinside);
+ if (qh JOGGLEmax < qh DISTround) {
+ fprintf (qh ferr, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+ qh JOGGLEmax, qh DISTround);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh MINvisible > REALmax/2) {
+ if (!qh MERGING)
+ qh MINvisible= qh DISTround;
+ else if (qh hull_dim <= 3)
+ qh MINvisible= qh premerge_centrum;
+ else
+ qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
+ if (qh APPROXhull && qh MINvisible > qh MINoutside)
+ qh MINvisible= qh MINoutside;
+ qh_option ("Visible-distance", NULL, &qh MINvisible);
+ }
+ if (qh MAXcoplanar > REALmax/2) {
+ qh MAXcoplanar= qh MINvisible;
+ qh_option ("U-coplanar-distance", NULL, &qh MAXcoplanar);
+ }
+ if (!qh APPROXhull) { /* user may specify qh MINoutside */
+ qh MINoutside= 2 * qh MINvisible;
+ if (qh premerge_cos < REALmax/2)
+ maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
+ qh_option ("Width-outside", NULL, &qh MINoutside);
+ }
+ qh WIDEfacet= qh MINoutside;
+ maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
+ maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
+ qh_option ("_wide-facet", NULL, &qh WIDEfacet);
+ if (qh MINvisible > qh MINoutside + 3 * REALepsilon
+ && !qh BESToutside && !qh FORCEoutput)
+ fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g. Flipped facets are likely.\n",
+ qh MINvisible, qh MINoutside);
+ qh max_vertex= qh DISTround;
+ qh min_vertex= -qh DISTround;
+ /* numeric constants reported in printsummary */
+} /* detroundoff */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="detsimplex">-</a>
+
+ qh_detsimplex( apex, points, dim, nearzero )
+ compute determinant of a simplex with point apex and base points
+
+ returns:
+ signed determinant and nearzero from qh_determinant
+
+ notes:
+ uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+ design:
+ construct qm_matrix by subtracting apex from points
+ compute determinate
+*/
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
+ pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+ coordT **rows;
+ int k, i=0;
+ realT det;
+
+ zinc_(Zdetsimplex);
+ gmcoord= qh gm_matrix;
+ rows= qh gm_row;
+ FOREACHpoint_(points) {
+ if (i == dim)
+ break;
+ rows[i++]= gmcoord;
+ coordp= point;
+ coorda= apex;
+ for (k= dim; k--; )
+ *(gmcoord++)= *coordp++ - *coorda++;
+ }
+ if (i < dim) {
+ fprintf (qh ferr, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
+ i, dim);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ det= qh_determinant (rows, dim, nearzero);
+ trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+ det, qh_pointid(apex), dim, *nearzero));
+ return det;
+} /* detsimplex */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="distnorm">-</a>
+
+ qh_distnorm( dim, point, normal, offset )
+ return distance from point to hyperplane at normal/offset
+
+ returns:
+ dist
+
+ notes:
+ dist > 0 if point is outside of hyperplane
+
+ see:
+ qh_distplane in geom.c
+*/
+realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp) {
+ coordT *normalp= normal, *coordp= point;
+ realT dist;
+ int k;
+
+ dist= *offsetp;
+ for (k= dim; k--; )
+ dist += *(coordp++) * *(normalp++);
+ return dist;
+} /* distnorm */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="distround">-</a>
+
+ qh_distround ( dimension, maxabs, maxsumabs )
+ compute maximum round-off error for a distance computation
+ to a normalized hyperplane
+ maxabs is the maximum absolute value of a coordinate
+ maxsumabs is the maximum possible sum of absolute coordinate values
+
+ returns:
+ max dist round for REALepsilon
+
+ notes:
+ calculate roundoff error according to
+ Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
+ use sqrt(dim) since one vector is normalized
+ or use maxsumabs since one vector is < 1
+*/
+realT qh_distround (int dimension, realT maxabs, realT maxsumabs) {
+ realT maxdistsum, maxround;
+
+ maxdistsum= sqrt (dimension) * maxabs;
+ minimize_( maxdistsum, maxsumabs);
+ maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+ /* adds maxabs for offset */
+ trace4((qh ferr, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
+ maxround, maxabs, maxsumabs, maxdistsum));
+ return maxround;
+} /* distround */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="divzero">-</a>
+
+ qh_divzero( numer, denom, mindenom1, zerodiv )
+ divide by a number that's nearly zero
+ mindenom1= minimum denominator for dividing into 1.0
+
+ returns:
+ quotient
+ sets zerodiv and returns 0.0 if it would overflow
+
+ design:
+ if numer is nearly zero and abs(numer) < abs(denom)
+ return numer/denom
+ else if numer is nearly zero
+ return 0 and zerodiv
+ else if denom/numer non-zero
+ return numer/denom
+ else
+ return 0 and zerodiv
+*/
+realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+ realT temp, numerx, denomx;
+
+
+ if (numer < mindenom1 && numer > -mindenom1) {
+ numerx= fabs_(numer);
+ denomx= fabs_(denom);
+ if (numerx < denomx) {
+ *zerodiv= False;
+ return numer/denom;
+ }else {
+ *zerodiv= True;
+ return 0.0;
+ }
+ }
+ temp= denom/numer;
+ if (temp > mindenom1 || temp < -mindenom1) {
+ *zerodiv= False;
+ return numer/denom;
+ }else {
+ *zerodiv= True;
+ return 0.0;
+ }
+} /* divzero */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="facetarea">-</a>
+
+ qh_facetarea( facet )
+ return area for a facet
+
+ notes:
+ if non-simplicial,
+ uses centrum to triangulate facet and sums the projected areas.
+ if (qh DELAUNAY),
+ computes projected area instead for last coordinate
+ assumes facet->normal exists
+ projecting tricoplanar facets to the hyperplane does not appear to make a difference
+
+ design:
+ if simplicial
+ compute area
+ else
+ for each ridge
+ compute area from centrum to ridge
+ negate area if upper Delaunay facet
+*/
+realT qh_facetarea (facetT *facet) {
+ vertexT *apex;
+ pointT *centrum;
+ realT area= 0.0;
+ ridgeT *ridge, **ridgep;
+
+ if (facet->simplicial) {
+ apex= SETfirstt_(facet->vertices, vertexT);
+ area= qh_facetarea_simplex (qh hull_dim, apex->point, facet->vertices,
+ apex, facet->toporient, facet->normal, &facet->offset);
+ }else {
+ if (qh CENTERtype == qh_AScentrum)
+ centrum= facet->center;
+ else
+ centrum= qh_getcentrum (facet);
+ FOREACHridge_(facet->ridges)
+ area += qh_facetarea_simplex (qh hull_dim, centrum, ridge->vertices,
+ NULL, (ridge->top == facet), facet->normal, &facet->offset);
+ if (qh CENTERtype != qh_AScentrum)
+ qh_memfree (centrum, qh normal_size);
+ }
+ if (facet->upperdelaunay && qh DELAUNAY)
+ area= -area; /* the normal should be [0,...,1] */
+ trace4((qh ferr, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
+ return area;
+} /* facetarea */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="facetarea_simplex">-</a>
+
+ qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
+ return area for a simplex defined by
+ an apex, a base of vertices, an orientation, and a unit normal
+ if simplicial or tricoplanar facet,
+ notvertex is defined and it is skipped in vertices
+
+ returns:
+ computes area of simplex projected to plane [normal,offset]
+ returns 0 if vertex too far below plane (qh WIDEfacet)
+ vertex can't be apex of tricoplanar facet
+
+ notes:
+ if (qh DELAUNAY),
+ computes projected area instead for last coordinate
+ uses qh gm_matrix/gm_row and qh hull_dim
+ helper function for qh_facetarea
+
+ design:
+ if Notvertex
+ translate simplex to apex
+ else
+ project simplex to normal/offset
+ translate simplex to apex
+ if Delaunay
+ set last row/column to 0 with -1 on diagonal
+ else
+ set last row to Normal
+ compute determinate
+ scale and flip sign for area
+*/
+realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices,
+ vertexT *notvertex, boolT toporient, coordT *normal, realT *offset) {
+ pointT *coorda, *coordp, *gmcoord;
+ coordT **rows, *normalp;
+ int k, i=0;
+ realT area, dist;
+ vertexT *vertex, **vertexp;
+ boolT nearzero;
+
+ gmcoord= qh gm_matrix;
+ rows= qh gm_row;
+ FOREACHvertex_(vertices) {
+ if (vertex == notvertex)
+ continue;
+ rows[i++]= gmcoord;
+ coorda= apex;
+ coordp= vertex->point;
+ normalp= normal;
+ if (notvertex) {
+ for (k= dim; k--; )
+ *(gmcoord++)= *coordp++ - *coorda++;
+ }else {
+ dist= *offset;
+ for (k= dim; k--; )
+ dist += *coordp++ * *normalp++;
+ if (dist < -qh WIDEfacet) {
+ zinc_(Znoarea);
+ return 0.0;
+ }
+ coordp= vertex->point;
+ normalp= normal;
+ for (k= dim; k--; )
+ *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+ }
+ }
+ if (i != dim-1) {
+ fprintf (qh ferr, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
+ i, dim);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ rows[i]= gmcoord;
+ if (qh DELAUNAY) {
+ for (i= 0; i < dim-1; i++)
+ rows[i][dim-1]= 0.0;
+ for (k= dim; k--; )
+ *(gmcoord++)= 0.0;
+ rows[dim-1][dim-1]= -1.0;
+ }else {
+ normalp= normal;
+ for (k= dim; k--; )
+ *(gmcoord++)= *normalp++;
+ }
+ zinc_(Zdetsimplex);
+ area= qh_determinant (rows, dim, &nearzero);
+ if (toporient)
+ area= -area;
+ area *= qh AREAfactor;
+ trace4((qh ferr, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+ area, qh_pointid(apex), toporient, nearzero));
+ return area;
+} /* facetarea_simplex */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="facetcenter">-</a>
+
+ qh_facetcenter( vertices )
+ return Voronoi center (Voronoi vertex) for a facet's vertices
+
+ returns:
+ return temporary point equal to the center
+
+ see:
+ qh_voronoi_center()
+*/
+pointT *qh_facetcenter (setT *vertices) {
+ setT *points= qh_settemp (qh_setsize (vertices));
+ vertexT *vertex, **vertexp;
+ pointT *center;
+
+ FOREACHvertex_(vertices)
+ qh_setappend (&points, vertex->point);
+ center= qh_voronoi_center (qh hull_dim-1, points);
+ qh_settempfree (&points);
+ return center;
+} /* facetcenter */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="findgooddist">-</a>
+
+ qh_findgooddist( point, facetA, dist, facetlist )
+ find best good facet visible for point from facetA
+ assumes facetA is visible from point
+
+ returns:
+ best facet, i.e., good facet that is furthest from point
+ distance to best facet
+ NULL if none
+
+ moves good, visible facets (and some other visible facets)
+ to end of qh facet_list
+
+ notes:
+ uses qh visit_id
+
+ design:
+ initialize bestfacet if facetA is good
+ move facetA to end of facetlist
+ for each facet on facetlist
+ for each unvisited neighbor of facet
+ move visible neighbors to end of facetlist
+ update best good neighbor
+ if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp,
+ facetT **facetlist) {
+ realT bestdist= -REALmax, dist;
+ facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+ boolT goodseen= False;
+
+ if (facetA->good) {
+ zinc_(Zcheckpart); /* calls from check_bestdist occur after print stats */
+ qh_distplane (point, facetA, &bestdist);
+ bestfacet= facetA;
+ goodseen= True;
+ }
+ qh_removefacet (facetA);
+ qh_appendfacet (facetA);
+ *facetlist= facetA;
+ facetA->visitid= ++qh visit_id;
+ FORALLfacet_(*facetlist) {
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid == qh visit_id)
+ continue;
+ neighbor->visitid= qh visit_id;
+ if (goodseen && !neighbor->good)
+ continue;
+ zinc_(Zcheckpart);
+ qh_distplane (point, neighbor, &dist);
+ if (dist > 0) {
+ qh_removefacet (neighbor);
+ qh_appendfacet (neighbor);
+ if (neighbor->good) {
+ goodseen= True;
+ if (dist > bestdist) {
+ bestdist= dist;
+ bestfacet= neighbor;
+ }
+ }
+ }
+ }
+ }
+ if (bestfacet) {
+ *distp= bestdist;
+ trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+ qh_pointid(point), bestdist, bestfacet->id));
+ return bestfacet;
+ }
+ trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n",
+ qh_pointid(point), facetA->id));
+ return NULL;
+} /* findgooddist */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="getarea">-</a>
+
+ qh_getarea( facetlist )
+ set area of all facets in facetlist
+ collect statistics
+
+ returns:
+ sets qh totarea/totvol to total area and volume of convex hull
+ for Delaunay triangulation, computes projected area of the lower or upper hull
+ ignores upper hull if qh ATinfinity
+
+ notes:
+ could compute outer volume by expanding facet area by rays from interior
+ the following attempt at perpendicular projection underestimated badly:
+ qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
+ * area/ qh hull_dim;
+ design:
+ for each facet on facetlist
+ compute facet->area
+ update qh.totarea and qh.totvol
+*/
+void qh_getarea (facetT *facetlist) {
+ realT area;
+ realT dist;
+ facetT *facet;
+
+ if (qh REPORTfreq)
+ fprintf (qh ferr, "computing area of each facet and volume of the convex hull\n");
+ else
+ trace1((qh ferr, "qh_getarea: computing volume and area for each facet\n"));
+ qh totarea= qh totvol= 0.0;
+ FORALLfacet_(facetlist) {
+ if (!facet->normal)
+ continue;
+ if (facet->upperdelaunay && qh ATinfinity)
+ continue;
+ facet->f.area= area= qh_facetarea (facet);
+ facet->isarea= True;
+ if (qh DELAUNAY) {
+ if (facet->upperdelaunay == qh UPPERdelaunay)
+ qh totarea += area;
+ }else {
+ qh totarea += area;
+ qh_distplane (qh interior_point, facet, &dist);
+ qh totvol += -dist * area/ qh hull_dim;
+ }
+ if (qh PRINTstatistics) {
+ wadd_(Wareatot, area);
+ wmax_(Wareamax, area);
+ wmin_(Wareamin, area);
+ }
+ }
+} /* getarea */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="gram_schmidt">-</a>
+
+ qh_gram_schmidt( dim, row )
+ implements Gram-Schmidt orthogonalization by rows
+
+ returns:
+ false if zero norm
+ overwrites rows[dim][dim]
+
+ notes:
+ see Golub & van Loan Algorithm 6.2-2
+ overflow due to small divisors not handled
+
+ design:
+ for each row
+ compute norm for row
+ if non-zero, normalize row
+ for each remaining rowA
+ compute inner product of row and rowA
+ reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(int dim, realT **row) {
+ realT *rowi, *rowj, norm;
+ int i, j, k;
+
+ for(i=0; i < dim; i++) {
+ rowi= row[i];
+ for (norm= 0.0, k= dim; k--; rowi++)
+ norm += *rowi * *rowi;
+ norm= sqrt(norm);
+ wmin_(Wmindenom, norm);
+ if (norm == 0.0) /* either 0 or overflow due to sqrt */
+ return False;
+ for(k= dim; k--; )
+ *(--rowi) /= norm;
+ for(j= i+1; j < dim; j++) {
+ rowj= row[j];
+ for(norm= 0.0, k=dim; k--; )
+ norm += *rowi++ * *rowj++;
+ for(k=dim; k--; )
+ *(--rowj) -= *(--rowi) * norm;
+ }
+ }
+ return True;
+} /* gram_schmidt */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="inthresholds">-</a>
+
+ qh_inthresholds( normal, angle )
+ return True if normal within qh.lower_/upper_threshold
+
+ returns:
+ estimate of angle by summing of threshold diffs
+ angle may be NULL
+ smaller "angle" is better
+
+ notes:
+ invalid if qh.SPLITthresholds
+
+ see:
+ qh.lower_threshold in qh_initbuild()
+ qh_initthresholds()
+
+ design:
+ for each dimension
+ test threshold
+*/
+boolT qh_inthresholds (coordT *normal, realT *angle) {
+ boolT within= True;
+ int k;
+ realT threshold;
+
+ if (angle)
+ *angle= 0.0;
+ for(k= 0; k < qh hull_dim; k++) {
+ threshold= qh lower_threshold[k];
+ if (threshold > -REALmax/2) {
+ if (normal[k] < threshold)
+ within= False;
+ if (angle) {
+ threshold -= normal[k];
+ *angle += fabs_(threshold);
+ }
+ }
+ if (qh upper_threshold[k] < REALmax/2) {
+ threshold= qh upper_threshold[k];
+ if (normal[k] > threshold)
+ within= False;
+ if (angle) {
+ threshold -= normal[k];
+ *angle += fabs_(threshold);
+ }
+ }
+ }
+ return within;
+} /* inthresholds */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="joggleinput">-</a>
+
+ qh_joggleinput()
+ randomly joggle input to Qhull by qh.JOGGLEmax
+ initial input is qh.first_point/qh.num_points of qh.hull_dim
+ repeated calls use qh.input_points/qh.num_points
+
+ returns:
+ joggles points at qh.first_point/qh.num_points
+ copies data to qh.input_points/qh.input_malloc if first time
+ determines qh.JOGGLEmax if it was zero
+ if qh.DELAUNAY
+ computes the Delaunay projection of the joggled points
+
+ notes:
+ if qh.DELAUNAY, unnecessarily joggles the last coordinate
+ the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+ design:
+ if qh.DELAUNAY
+ set qh.SCALElast for reduced precision errors
+ if first call
+ initialize qh.input_points to the original input points
+ if qh.JOGGLEmax == 0
+ determine default qh.JOGGLEmax
+ else
+ increase qh.JOGGLEmax according to qh.build_cnt
+ joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+ if qh.DELAUNAY
+ sets the Delaunay projection
+*/
+void qh_joggleinput (void) {
+ int size, i, seed;
+ coordT *coordp, *inputp;
+ realT randr, randa, randb;
+
+ if (!qh input_points) { /* first call */
+ qh input_points= qh first_point;
+ qh input_malloc= qh POINTSmalloc;
+ size= qh num_points * qh hull_dim * sizeof(coordT);
+ if (!(qh first_point=(coordT*)malloc(size))) {
+ fprintf(qh ferr, "qhull error: insufficient memory to joggle %d points\n",
+ qh num_points);
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ qh POINTSmalloc= True;
+ if (qh JOGGLEmax == 0.0) {
+ qh JOGGLEmax= qh_detjoggle (qh input_points, qh num_points, qh hull_dim);
+ qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+ }
+ }else { /* repeated call */
+ if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
+ if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+ realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
+ if (qh JOGGLEmax < maxjoggle) {
+ qh JOGGLEmax *= qh_JOGGLEincrease;
+ minimize_(qh JOGGLEmax, maxjoggle);
+ }
+ }
+ }
+ qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+ }
+ if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
+ fprintf (qh ferr, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input. If possible, recompile Qhull with higher-precision reals.\n",
+ qh JOGGLEmax);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+ seed= qh_RANDOMint;
+ qh_option ("_joggle-seed", &seed, NULL);
+ trace0((qh ferr, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
+ qh JOGGLEmax, seed));
+ inputp= qh input_points;
+ coordp= qh first_point;
+ randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
+ randb= -qh JOGGLEmax;
+ size= qh num_points * qh hull_dim;
+ for (i= size; i--; ) {
+ randr= qh_RANDOMint;
+ *(coordp++)= *(inputp++) + (randr * randa + randb);
+ }
+ if (qh DELAUNAY) {
+ qh last_low= qh last_high= qh last_newhigh= REALmax;
+ qh_setdelaunay (qh hull_dim, qh num_points, qh first_point);
+ }
+} /* joggleinput */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="maxabsval">-</a>
+
+ qh_maxabsval( normal, dim )
+ return pointer to maximum absolute value of a dim vector
+ returns NULL if dim=0
+*/
+realT *qh_maxabsval (realT *normal, int dim) {
+ realT maxval= -REALmax;
+ realT *maxp= NULL, *colp, absval;
+ int k;
+
+ for (k= dim, colp= normal; k--; colp++) {
+ absval= fabs_(*colp);
+ if (absval > maxval) {
+ maxval= absval;
+ maxp= colp;
+ }
+ }
+ return maxp;
+} /* maxabsval */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="maxmin">-</a>
+
+ qh_maxmin( points, numpoints, dimension )
+ return max/min points for each dimension
+ determine max and min coordinates
+
+ returns:
+ returns a temporary set of max and min points
+ may include duplicate points. Does not include qh.GOODpoint
+ sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+ qh.MAXlastcoord, qh.MINlastcoord
+ initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+ notes:
+ loop duplicated in qh_detjoggle()
+
+ design:
+ initialize global precision variables
+ checks definition of REAL...
+ for each dimension
+ for each point
+ collect maximum and minimum point
+ collect maximum of maximums and minimum of minimums
+ determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
+ int k;
+ realT maxcoord, temp;
+ pointT *minimum, *maximum, *point, *pointtemp;
+ setT *set;
+
+ qh max_outside= 0.0;
+ qh MAXabs_coord= 0.0;
+ qh MAXwidth= -REALmax;
+ qh MAXsumcoord= 0.0;
+ qh min_vertex= 0.0;
+ qh WAScoplanar= False;
+ if (qh ZEROcentrum)
+ qh ZEROall_ok= True;
+ if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+ && REALmax > 0.0 && -REALmax < 0.0)
+ ; /* all ok */
+ else {
+ fprintf (qh ferr, "qhull error: floating point constants in user.h are wrong\n\
+REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
+ REALepsilon, REALmin, REALmax, -REALmax);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ set= qh_settemp(2*dimension);
+ for(k= 0; k < dimension; k++) {
+ if (points == qh GOODpointp)
+ minimum= maximum= points + dimension;
+ else
+ minimum= maximum= points;
+ FORALLpoint_(points, numpoints) {
+ if (point == qh GOODpointp)
+ continue;
+ if (maximum[k] < point[k])
+ maximum= point;
+ else if (minimum[k] > point[k])
+ minimum= point;
+ }
+ if (k == dimension-1) {
+ qh MINlastcoord= minimum[k];
+ qh MAXlastcoord= maximum[k];
+ }
+ if (qh SCALElast && k == dimension-1)
+ maxcoord= qh MAXwidth;
+ else {
+ maxcoord= fmax_(maximum[k], -minimum[k]);
+ if (qh GOODpointp) {
+ temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
+ maximize_(maxcoord, temp);
+ }
+ temp= maximum[k] - minimum[k];
+ maximize_(qh MAXwidth, temp);
+ }
+ maximize_(qh MAXabs_coord, maxcoord);
+ qh MAXsumcoord += maxcoord;
+ qh_setappend (&set, maximum);
+ qh_setappend (&set, minimum);
+ /* calculation of qh NEARzero is based on error formula 4.4-13 of
+ Golub & van Loan, authors say n^3 can be ignored and 10 be used in
+ place of rho */
+ qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
+ }
+ if (qh IStracing >=1)
+ qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set);
+ return(set);
+} /* maxmin */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="maxouter">-</a>
+
+ qh_maxouter()
+ return maximum distance from facet to outer plane
+ normally this is qh.max_outside+qh.DISTround
+ does not include qh.JOGGLEmax
+
+ see:
+ qh_outerinner()
+
+ notes:
+ need to add another qh.DISTround if testing actual point with computation
+
+ for joggle:
+ qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+ need to use Wnewvertexmax since could have a coplanar point for a high
+ facet that is replaced by a low facet
+ need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter (void) {
+ realT dist;
+
+ dist= fmax_(qh max_outside, qh DISTround);
+ dist += qh DISTround;
+ trace4((qh ferr, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
+ return dist;
+} /* maxouter */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="maxsimplex">-</a>
+
+ qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
+ determines maximum simplex for a set of points
+ starts from points already in simplex
+ skips qh.GOODpointp (assumes that it isn't in maxpoints)
+
+ returns:
+ simplex with dim+1 points
+
+ notes:
+ assumes at least pointsneeded points in points
+ maximizes determinate for x,y,z,w, etc.
+ uses maxpoints as long as determinate is clearly non-zero
+
+ design:
+ initialize simplex with at least two points
+ (find points with max or min x coordinate)
+ for each remaining dimension
+ add point that maximizes the determinate
+ (use points from maxpoints first)
+*/
+void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+ pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+ boolT nearzero, maxnearzero= False;
+ int k, sizinit;
+ realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
+
+ sizinit= qh_setsize (*simplex);
+ if (sizinit < 2) {
+ if (qh_setsize (maxpoints) >= 2) {
+ FOREACHpoint_(maxpoints) {
+ if (maxcoord < point[0]) {
+ maxcoord= point[0];
+ maxx= point;
+ }
+ if (mincoord > point[0]) {
+ mincoord= point[0];
+ minx= point;
+ }
+ }
+ }else {
+ FORALLpoint_(points, numpoints) {
+ if (point == qh GOODpointp)
+ continue;
+ if (maxcoord < point[0]) {
+ maxcoord= point[0];
+ maxx= point;
+ }
+ if (mincoord > point[0]) {
+ mincoord= point[0];
+ minx= point;
+ }
+ }
+ }
+ qh_setunique (simplex, minx);
+ if (qh_setsize (*simplex) < 2)
+ qh_setunique (simplex, maxx);
+ sizinit= qh_setsize (*simplex);
+ if (sizinit < 2) {
+ qh_precision ("input has same x coordinate");
+ if (zzval_(Zsetplane) > qh hull_dim+1) {
+ fprintf (qh ferr, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
+ qh_setsize(maxpoints)+numpoints);
+ qh_errexit (qh_ERRprec, NULL, NULL);
+ }else {
+ fprintf (qh ferr, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ }
+ }
+ for(k= sizinit; k < dim+1; k++) {
+ maxpoint= NULL;
+ maxdet= -REALmax;
+ FOREACHpoint_(maxpoints) {
+ if (!qh_setin (*simplex, point)) {
+ det= qh_detsimplex(point, *simplex, k, &nearzero);
+ if ((det= fabs_(det)) > maxdet) {
+ maxdet= det;
+ maxpoint= point;
+ maxnearzero= nearzero;
+ }
+ }
+ }
+ if (!maxpoint || maxnearzero) {
+ zinc_(Zsearchpoints);
+ if (!maxpoint) {
+ trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
+ }else {
+ trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
+ k+1, qh_pointid(maxpoint), maxdet));
+ }
+ FORALLpoint_(points, numpoints) {
+ if (point == qh GOODpointp)
+ continue;
+ if (!qh_setin (*simplex, point)) {
+ det= qh_detsimplex(point, *simplex, k, &nearzero);
+ if ((det= fabs_(det)) > maxdet) {
+ maxdet= det;
+ maxpoint= point;
+ maxnearzero= nearzero;
+ }
+ }
+ }
+ } /* !maxpoint */
+ if (!maxpoint) {
+ fprintf (qh ferr, "qhull internal error (qh_maxsimplex): not enough points available\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh_setappend(simplex, maxpoint);
+ trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
+ qh_pointid(maxpoint), k+1, maxdet));
+ } /* k */
+} /* maxsimplex */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="minabsval">-</a>
+
+ qh_minabsval( normal, dim )
+ return minimum absolute value of a dim vector
+*/
+realT qh_minabsval (realT *normal, int dim) {
+ realT minval= 0;
+ realT maxval= 0;
+ realT *colp;
+ int k;
+
+ for (k= dim, colp= normal; k--; colp++) {
+ maximize_(maxval, *colp);
+ minimize_(minval, *colp);
+ }
+ return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="mindiff">-</a>
+
+ qh_mindif( vecA, vecB, dim )
+ return index of min abs. difference of two vectors
+*/
+int qh_mindiff (realT *vecA, realT *vecB, int dim) {
+ realT mindiff= REALmax, diff;
+ realT *vecAp= vecA, *vecBp= vecB;
+ int k, mink= 0;
+
+ for (k= 0; k < dim; k++) {
+ diff= *vecAp++ - *vecBp++;
+ diff= fabs_(diff);
+ if (diff < mindiff) {
+ mindiff= diff;
+ mink= k;
+ }
+ }
+ return mink;
+} /* mindiff */
+
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="orientoutside">-</a>
+
+ qh_orientoutside( facet )
+ make facet outside oriented via qh.interior_point
+
+ returns:
+ True if facet reversed orientation.
+*/
+boolT qh_orientoutside (facetT *facet) {
+ int k;
+ realT dist;
+
+ qh_distplane (qh interior_point, facet, &dist);
+ if (dist > 0) {
+ for (k= qh hull_dim; k--; )
+ facet->normal[k]= -facet->normal[k];
+ facet->offset= -facet->offset;
+ return True;
+ }
+ return False;
+} /* orientoutside */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="outerinner">-</a>
+
+ qh_outerinner( facet, outerplane, innerplane )
+ if facet and qh.maxoutdone (i.e., qh_check_maxout)
+ returns outer and inner plane for facet
+ else
+ returns maximum outer and inner plane
+ accounts for qh.JOGGLEmax
+
+ see:
+ qh_maxouter(), qh_check_bestdist(), qh_check_points()
+
+ notes:
+ outerplaner or innerplane may be NULL
+
+ includes qh.DISTround for actual points
+ adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane) {
+ realT dist, mindist;
+ vertexT *vertex, **vertexp;
+
+ if (outerplane) {
+ if (!qh_MAXoutside || !facet || !qh maxoutdone) {
+ *outerplane= qh_maxouter(); /* includes qh.DISTround */
+ }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside
+ *outerplane= facet->maxoutside + qh DISTround;
+#endif
+
+ }
+ if (qh JOGGLEmax < REALmax/2)
+ *outerplane += qh JOGGLEmax * sqrt (qh hull_dim);
+ }
+ if (innerplane) {
+ if (facet) {
+ mindist= REALmax;
+ FOREACHvertex_(facet->vertices) {
+ zinc_(Zdistio);
+ qh_distplane (vertex->point, facet, &dist);
+ minimize_(mindist, dist);
+ }
+ *innerplane= mindist - qh DISTround;
+ }else
+ *innerplane= qh min_vertex - qh DISTround;
+ if (qh JOGGLEmax < REALmax/2)
+ *innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
+ }
+} /* outerinner */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="pointdist">-</a>
+
+ qh_pointdist( point1, point2, dim )
+ return distance between two points
+
+ notes:
+ returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+ coordT dist, diff;
+ int k;
+
+ dist= 0.0;
+ for (k= (dim > 0 ? dim : -dim); k--; ) {
+ diff= *point1++ - *point2++;
+ dist += diff * diff;
+ }
+ if (dim > 0)
+ return(sqrt(dist));
+ return dist;
+} /* pointdist */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="printmatrix">-</a>
+
+ qh_printmatrix( fp, string, rows, numrow, numcol )
+ print matrix to fp given by row vectors
+ print string as header
+
+ notes:
+ print a vector by qh_printmatrix(fp, "", &vect, 1, len)
+*/
+void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol) {
+ realT *rowp;
+ realT r; /*bug fix*/
+ int i,k;
+
+ fprintf (fp, "%s\n", string);
+ for (i= 0; i < numrow; i++) {
+ rowp= rows[i];
+ for (k= 0; k < numcol; k++) {
+ r= *rowp++;
+ fprintf (fp, "%6.3g ", r);
+ }
+ fprintf (fp, "\n");
+ }
+} /* printmatrix */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="printpoints">-</a>
+
+ qh_printpoints( fp, string, points )
+ print pointids to fp for a set of points
+ if string, prints string and 'p' point ids
+*/
+void qh_printpoints (FILE *fp, char *string, setT *points) {
+ pointT *point, **pointp;
+
+ if (string) {
+ fprintf (fp, "%s", string);
+ FOREACHpoint_(points)
+ fprintf (fp, " p%d", qh_pointid(point));
+ fprintf (fp, "\n");
+ }else {
+ FOREACHpoint_(points)
+ fprintf (fp, " %d", qh_pointid(point));
+ fprintf (fp, "\n");
+ }
+} /* printpoints */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="projectinput">-</a>
+
+ qh_projectinput()
+ project input points using qh.lower_bound/upper_bound and qh DELAUNAY
+ if qh.lower_bound[k]=qh.upper_bound[k]= 0,
+ removes dimension k
+ if halfspace intersection
+ removes dimension k from qh.feasible_point
+ input points in qh first_point, num_points, input_dim
+
+ returns:
+ new point array in qh first_point of qh hull_dim coordinates
+ sets qh POINTSmalloc
+ if qh DELAUNAY
+ projects points to paraboloid
+ lowbound/highbound is also projected
+ if qh ATinfinity
+ adds point "at-infinity"
+ if qh POINTSmalloc
+ frees old point array
+
+ notes:
+ checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+ design:
+ sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+ determines newdim and newnum for qh hull_dim and qh num_points
+ projects points to newpoints
+ projects qh.lower_bound to itself
+ projects qh.upper_bound to itself
+ if qh DELAUNAY
+ if qh ATINFINITY
+ projects points to paraboloid
+ computes "infinity" point as vertex average and 10% above all points
+ else
+ uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput (void) {
+ int k,i;
+ int newdim= qh input_dim, newnum= qh num_points;
+ signed char *project;
+ int size= (qh input_dim+1)*sizeof(*project);
+ pointT *newpoints, *coord, *infinity;
+ realT paraboloid, maxboloid= 0;
+
+ project= (signed char*)qh_memalloc (size);
+ memset ((char*)project, 0, size);
+ for (k= 0; k < qh input_dim; k++) { /* skip Delaunay bound */
+ if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
+ project[k]= -1;
+ newdim--;
+ }
+ }
+ if (qh DELAUNAY) {
+ project[k]= 1;
+ newdim++;
+ if (qh ATinfinity)
+ newnum++;
+ }
+ if (newdim != qh hull_dim) {
+ fprintf(qh ferr, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
+ qh_errexit(qh_ERRqhull, NULL, NULL);
+ }
+ if (!(newpoints=(coordT*)malloc(newnum*newdim*sizeof(coordT)))){
+ fprintf(qh ferr, "qhull error: insufficient memory to project %d points\n",
+ qh num_points);
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ qh_projectpoints (project, qh input_dim+1, qh first_point,
+ qh num_points, qh input_dim, newpoints, newdim);
+ trace1((qh ferr, "qh_projectinput: updating lower and upper_bound\n"));
+ qh_projectpoints (project, qh input_dim+1, qh lower_bound,
+ 1, qh input_dim+1, qh lower_bound, newdim+1);
+ qh_projectpoints (project, qh input_dim+1, qh upper_bound,
+ 1, qh input_dim+1, qh upper_bound, newdim+1);
+ if (qh HALFspace) {
+ if (!qh feasible_point) {
+ fprintf(qh ferr, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+ qh_errexit(qh_ERRqhull, NULL, NULL);
+ }
+ qh_projectpoints (project, qh input_dim, qh feasible_point,
+ 1, qh input_dim, qh feasible_point, newdim);
+ }
+ qh_memfree(project, ((qh input_dim+1)*sizeof(*project)));
+ if (qh POINTSmalloc)
+ free (qh first_point);
+ qh first_point= newpoints;
+ qh POINTSmalloc= True;
+ if (qh DELAUNAY && qh ATinfinity) {
+ coord= qh first_point;
+ infinity= qh first_point + qh hull_dim * qh num_points;
+ for (k=qh hull_dim-1; k--; )
+ infinity[k]= 0.0;
+ for (i=qh num_points; i--; ) {
+ paraboloid= 0.0;
+ for (k=qh hull_dim-1; k--; ) {
+ paraboloid += *coord * *coord;
+ infinity[k] += *coord;
+ coord++;
+ }
+ *(coord++)= paraboloid;
+ maximize_(maxboloid, paraboloid);
+ }
+ /* coord == infinity */
+ for (k=qh hull_dim-1; k--; )
+ *(coord++) /= qh num_points;
+ *(coord++)= maxboloid * 1.1;
+ qh num_points++;
+ trace0((qh ferr, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+ }else if (qh DELAUNAY) /* !qh ATinfinity */
+ qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
+} /* projectinput */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="projectpoints">-</a>
+
+ qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
+ project points/numpoints/dim to newpoints/newdim
+ if project[k] == -1
+ delete dimension k
+ if project[k] == 1
+ add dimension k by duplicating previous column
+ n is size of project
+
+ notes:
+ newpoints may be points if only adding dimension at end
+
+ design:
+ check that 'project' and 'newdim' agree
+ for each dimension
+ if project == -1
+ skip dimension
+ else
+ determine start of column in newpoints
+ determine start of column in points
+ if project == +1, duplicate previous column
+ copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints (signed char *project, int n, realT *points,
+ int numpoints, int dim, realT *newpoints, int newdim) {
+ int testdim= dim, oldk=0, newk=0, i,j=0,k;
+ realT *newp, *oldp;
+
+ for (k= 0; k < n; k++)
+ testdim += project[k];
+ if (testdim != newdim) {
+ fprintf (qh ferr, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+ newdim, testdim);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ for (j= 0; j<n; j++) {
+ if (project[j] == -1)
+ oldk++;
+ else {
+ newp= newpoints+newk++;
+ if (project[j] == +1) {
+ if (oldk >= dim)
+ continue;
+ oldp= points+oldk;
+ }else
+ oldp= points+oldk++;
+ for (i=numpoints; i--; ) {
+ *newp= *oldp;
+ newp += newdim;
+ oldp += dim;
+ }
+ }
+ if (oldk >= dim)
+ break;
+ }
+ trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
+ numpoints, dim, newdim));
+} /* projectpoints */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="rand">-</a>
+
+ qh_rand()
+ qh_srand( seed )
+ generate pseudo-random number between 1 and 2^31 -2
+
+ notes:
+ from Park & Miller's minimimal standard random number generator
+ Communications of the ACM, 31:1192-1201, 1988.
+ does not use 0 or 2^31 -1
+ this is silently enforced by qh_srand()
+ can make 'Rn' much faster by moving qh_rand to qh_distplane
+*/
+int qh_rand_seed= 1; /* define as global variable instead of using qh */
+
+int qh_rand( void) {
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773 /* m div a */
+#define qh_rand_r 2836 /* m mod a */
+ int lo, hi, test;
+ int seed = qh_rand_seed;
+
+ hi = seed / qh_rand_q; /* seed div q */
+ lo = seed % qh_rand_q; /* seed mod q */
+ test = qh_rand_a * lo - qh_rand_r * hi;
+ if (test > 0)
+ seed= test;
+ else
+ seed= test + qh_rand_m;
+ qh_rand_seed= seed;
+ /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax; for testing */
+ /* seed = qh_RANDOMmax; for testing */
+ return seed;
+} /* rand */
+
+void qh_srand( int seed) {
+ if (seed < 1)
+ qh_rand_seed= 1;
+ else if (seed >= qh_rand_m)
+ qh_rand_seed= qh_rand_m - 1;
+ else
+ qh_rand_seed= seed;
+} /* qh_srand */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="randomfactor">-</a>
+
+ qh_randomfactor()
+ return a random factor within qh.RANDOMmax of 1.0
+
+ notes:
+ qh.RANDOMa/b are defined in global.c
+*/
+realT qh_randomfactor (void) {
+ realT randr;
+
+ randr= qh_RANDOMint;
+ return randr * qh RANDOMa + qh RANDOMb;
+} /* randomfactor */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="randommatrix">-</a>
+
+ qh_randommatrix( buffer, dim, rows )
+ generate a random dim X dim matrix in range [-1,1]
+ assumes buffer is [dim+1, dim]
+
+ returns:
+ sets buffer to random numbers
+ sets rows to rows of buffer
+ sets row[dim] as scratch row
+*/
+void qh_randommatrix (realT *buffer, int dim, realT **rows) {
+ int i, k;
+ realT **rowi, *coord, realr;
+
+ coord= buffer;
+ rowi= rows;
+ for (i=0; i < dim; i++) {
+ *(rowi++)= coord;
+ for (k=0; k < dim; k++) {
+ realr= qh_RANDOMint;
+ *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+ }
+ }
+ *rowi= coord;
+} /* randommatrix */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="rotateinput">-</a>
+
+ qh_rotateinput( rows )
+ rotate input using row matrix
+ input points given by qh first_point, num_points, hull_dim
+ assumes rows[dim] is a scratch buffer
+ if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+ returns:
+ rotated input
+ sets qh POINTSmalloc
+
+ design:
+ see qh_rotatepoints
+*/
+void qh_rotateinput (realT **rows) {
+
+ if (!qh POINTSmalloc) {
+ qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+ qh POINTSmalloc= True;
+ }
+ qh_rotatepoints (qh first_point, qh num_points, qh hull_dim, rows);
+} /* rotateinput */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="rotatepoints">-</a>
+
+ qh_rotatepoints( points, numpoints, dim, row )
+ rotate numpoints points by a d-dim row matrix
+ assumes rows[dim] is a scratch buffer
+
+ returns:
+ rotated points in place
+
+ design:
+ for each point
+ for each coordinate
+ use row[dim] to compute partial inner product
+ for each coordinate
+ rotate by partial inner product
+*/
+void qh_rotatepoints (realT *points, int numpoints, int dim, realT **row) {
+ realT *point, *rowi, *coord= NULL, sum, *newval;
+ int i,j,k;
+
+ if (qh IStracing >= 1)
+ qh_printmatrix (qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+ for (point= points, j= numpoints; j--; point += dim) {
+ newval= row[dim];
+ for (i= 0; i < dim; i++) {
+ rowi= row[i];
+ coord= point;
+ for (sum= 0.0, k= dim; k--; )
+ sum += *rowi++ * *coord++;
+ *(newval++)= sum;
+ }
+ for (k= dim; k--; )
+ *(--coord)= *(--newval);
+ }
+} /* rotatepoints */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="scaleinput">-</a>
+
+ qh_scaleinput()
+ scale input points using qh low_bound/high_bound
+ input points given by qh first_point, num_points, hull_dim
+ if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+ returns:
+ scales coordinates of points to low_bound[k], high_bound[k]
+ sets qh POINTSmalloc
+
+ design:
+ see qh_scalepoints
+*/
+void qh_scaleinput (void) {
+
+ if (!qh POINTSmalloc) {
+ qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+ qh POINTSmalloc= True;
+ }
+ qh_scalepoints (qh first_point, qh num_points, qh hull_dim,
+ qh lower_bound, qh upper_bound);
+} /* scaleinput */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="scalelast">-</a>
+
+ qh_scalelast( points, numpoints, dim, low, high, newhigh )
+ scale last coordinate to [0,m] for Delaunay triangulations
+ input points given by points, numpoints, dim
+
+ returns:
+ changes scale of last coordinate from [low, high] to [0, newhigh]
+ overwrites last coordinate of each point
+ saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+ notes:
+ when called by qh_setdelaunay, low/high may not match actual data
+
+ design:
+ compute scale and shift factors
+ apply to last coordinate of each point
+*/
+void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+ coordT high, coordT newhigh) {
+ realT scale, shift;
+ coordT *coord;
+ int i;
+ boolT nearzero= False;
+
+ trace4((qh ferr, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
+ low, high, newhigh));
+ qh last_low= low;
+ qh last_high= high;
+ qh last_newhigh= newhigh;
+ scale= qh_divzero (newhigh, high - low,
+ qh MINdenom_1, &nearzero);
+ if (nearzero) {
+ if (qh DELAUNAY)
+ fprintf (qh ferr, "qhull input error: can not scale last coordinate. Input is cocircular\n or cospherical. Use option 'Qz' to add a point at infinity.\n");
+ else
+ fprintf (qh ferr, "qhull input error: can not scale last coordinate. New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
+ newhigh, low, high, high-low);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ shift= - low * newhigh / (high-low);
+ coord= points + dim - 1;
+ for (i= numpoints; i--; coord += dim)
+ *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="scalepoints">-</a>
+
+ qh_scalepoints( points, numpoints, dim, newlows, newhighs )
+ scale points to new lowbound and highbound
+ retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+ returns:
+ scaled points
+ overwrites old points
+
+ design:
+ for each coordinate
+ compute current low and high bound
+ compute scale and shift factors
+ scale all points
+ enforce new low and high bound for all points
+*/
+void qh_scalepoints (pointT *points, int numpoints, int dim,
+ realT *newlows, realT *newhighs) {
+ int i,k;
+ realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+ boolT nearzero= False;
+
+ for (k= 0; k < dim; k++) {
+ newhigh= newhighs[k];
+ newlow= newlows[k];
+ if (newhigh > REALmax/2 && newlow < -REALmax/2)
+ continue;
+ low= REALmax;
+ high= -REALmax;
+ for (i= numpoints, coord= points+k; i--; coord += dim) {
+ minimize_(low, *coord);
+ maximize_(high, *coord);
+ }
+ if (newhigh > REALmax/2)
+ newhigh= high;
+ if (newlow < -REALmax/2)
+ newlow= low;
+ if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
+ fprintf (qh ferr, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+ k, k, newhigh, newlow);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ scale= qh_divzero (newhigh - newlow, high - low,
+ qh MINdenom_1, &nearzero);
+ if (nearzero) {
+ fprintf (qh ferr, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+ k, newlow, newhigh, low, high);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ shift= (newlow * high - low * newhigh)/(high-low);
+ coord= points+k;
+ for (i= numpoints; i--; coord += dim)
+ *coord= *coord * scale + shift;
+ coord= points+k;
+ if (newlow < newhigh) {
+ mincoord= newlow;
+ maxcoord= newhigh;
+ }else {
+ mincoord= newhigh;
+ maxcoord= newlow;
+ }
+ for (i= numpoints; i--; coord += dim) {
+ minimize_(*coord, maxcoord); /* because of roundoff error */
+ maximize_(*coord, mincoord);
+ }
+ trace0((qh ferr, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
+ k, low, high, newlow, newhigh, numpoints, scale, shift));
+ }
+} /* scalepoints */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="setdelaunay">-</a>
+
+ qh_setdelaunay( dim, count, points )
+ project count points to dim-d paraboloid for Delaunay triangulation
+
+ dim is one more than the dimension of the input set
+ assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+ points is a dim*count realT array. The first dim-1 coordinates
+ are the coordinates of the first input point. array[dim] is
+ the first coordinate of the second input point. array[2*dim] is
+ the first coordinate of the third input point.
+
+ if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+ calls qh_scalelast to scale the last coordinate the same as the other points
+
+ returns:
+ for each point
+ sets point[dim-1] to sum of squares of coordinates
+ scale points to 'Qbb' if needed
+
+ notes:
+ to project one point, use
+ qh_setdelaunay (qh hull_dim, 1, point)
+
+ Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
+ the coordinates after the original projection.
+
+*/
+void qh_setdelaunay (int dim, int count, pointT *points) {
+ int i, k;
+ coordT *coordp, coord;
+ realT paraboloid;
+
+ trace0((qh ferr, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+ coordp= points;
+ for (i= 0; i < count; i++) {
+ coord= *coordp++;
+ paraboloid= coord*coord;
+ for (k= dim-2; k--; ) {
+ coord= *coordp++;
+ paraboloid += coord*coord;
+ }
+ *coordp++ = paraboloid;
+ }
+ if (qh last_low < REALmax/2)
+ qh_scalelast (points, count, dim, qh last_low, qh last_high, qh last_newhigh);
+} /* setdelaunay */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="sethalfspace">-</a>
+
+ qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
+ set point to dual of halfspace relative to feasible point
+ halfspace is normal coefficients and offset.
+
+ returns:
+ false if feasible point is outside of hull (error message already reported)
+ overwrites coordinates for point at dim coords
+ nextp= next point (coords)
+
+ design:
+ compute distance from feasible point to halfspace
+ divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp,
+ coordT *normal, coordT *offset, coordT *feasible) {
+ coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+ realT dist;
+ realT r; /*bug fix*/
+ int k;
+ boolT zerodiv;
+
+ dist= *offset;
+ for (k= dim; k--; )
+ dist += *(normp++) * *(feasiblep++);
+ if (dist > 0)
+ goto LABELerroroutside;
+ normp= normal;
+ if (dist < -qh MINdenom) {
+ for (k= dim; k--; )
+ *(coordp++)= *(normp++) / -dist;
+ }else {
+ for (k= dim; k--; ) {
+ *(coordp++)= qh_divzero (*(normp++), -dist, qh MINdenom_1, &zerodiv);
+ if (zerodiv)
+ goto LABELerroroutside;
+ }
+ }
+ *nextp= coordp;
+ if (qh IStracing >= 4) {
+ fprintf (qh ferr, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+ for (k= dim, coordp= coords; k--; ) {
+ r= *coordp++;
+ fprintf (qh ferr, " %6.2g", r);
+ }
+ fprintf (qh ferr, "\n");
+ }
+ return True;
+LABELerroroutside:
+ feasiblep= feasible;
+ normp= normal;
+ fprintf(qh ferr, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+ for (k= dim; k--; )
+ fprintf (qh ferr, qh_REAL_1, r=*(feasiblep++));
+ fprintf (qh ferr, "\n halfspace: ");
+ for (k= dim; k--; )
+ fprintf (qh ferr, qh_REAL_1, r=*(normp++));
+ fprintf (qh ferr, "\n at offset: ");
+ fprintf (qh ferr, qh_REAL_1, *offset);
+ fprintf (qh ferr, " and distance: ");
+ fprintf (qh ferr, qh_REAL_1, dist);
+ fprintf (qh ferr, "\n");
+ return False;
+} /* sethalfspace */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="sethalfspace_all">-</a>
+
+ qh_sethalfspace_all( dim, count, halfspaces, feasible )
+ generate dual for halfspace intersection with feasible point
+ array of count halfspaces
+ each halfspace is normal coefficients followed by offset
+ the origin is inside the halfspace if the offset is negative
+
+ returns:
+ malloc'd array of count X dim-1 points
+
+ notes:
+ call before qh_init_B or qh_initqhull_globals
+ unused/untested code: please email bradb@shore.net if this works ok for you
+ If using option 'Fp', also set qh feasible_point. It is a malloc'd array
+ that is freed by qh_freebuffers.
+
+ design:
+ see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible) {
+ int i, newdim;
+ pointT *newpoints;
+ coordT *coordp, *normalp, *offsetp;
+
+ trace0((qh ferr, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+ newdim= dim - 1;
+ if (!(newpoints=(coordT*)malloc(count*newdim*sizeof(coordT)))){
+ fprintf(qh ferr, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+ count);
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ coordp= newpoints;
+ normalp= halfspaces;
+ for (i= 0; i < count; i++) {
+ offsetp= normalp + newdim;
+ if (!qh_sethalfspace (newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+ fprintf (qh ferr, "The halfspace was at index %d\n", i);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ normalp= offsetp + 1;
+ }
+ return newpoints;
+} /* sethalfspace_all */
+
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="sharpnewfacets">-</a>
+
+ qh_sharpnewfacets()
+
+ returns:
+ true if could be an acute angle (facets in different quadrants)
+
+ notes:
+ for qh_findbest
+
+ design:
+ for all facets on qh.newfacet_list
+ if two facets are in different quadrants
+ set issharp
+*/
+boolT qh_sharpnewfacets () {
+ facetT *facet;
+ boolT issharp = False;
+ int *quadrant, k;
+
+ quadrant= (int*)qh_memalloc (qh hull_dim * sizeof(int));
+ FORALLfacet_(qh newfacet_list) {
+ if (facet == qh newfacet_list) {
+ for (k= qh hull_dim; k--; )
+ quadrant[ k]= (facet->normal[ k] > 0);
+ }else {
+ for (k= qh hull_dim; k--; ) {
+ if (quadrant[ k] != (facet->normal[ k] > 0)) {
+ issharp= True;
+ break;
+ }
+ }
+ }
+ if (issharp)
+ break;
+ }
+ qh_memfree( quadrant, qh hull_dim * sizeof(int));
+ trace3((qh ferr, "qh_sharpnewfacets: %d\n", issharp));
+ return issharp;
+} /* sharpnewfacets */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="voronoi_center">-</a>
+
+ qh_voronoi_center( dim, points )
+ return Voronoi center for a set of points
+ dim is the orginal dimension of the points
+ gh.gm_matrix/qh.gm_row are scratch buffers
+
+ returns:
+ center as a temporary point
+ if non-simplicial,
+ returns center for max simplex of points
+
+ notes:
+ from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+ design:
+ if non-simplicial
+ determine max simplex for points
+ translate point0 of simplex to origin
+ compute sum of squares of diagonal
+ compute determinate
+ compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center (int dim, setT *points) {
+ pointT *point, **pointp, *point0;
+ pointT *center= (pointT*)qh_memalloc (qh center_size);
+ setT *simplex;
+ int i, j, k, size= qh_setsize(points);
+ coordT *gmcoord;
+ realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+ boolT nearzero, infinite;
+
+ if (size == dim+1)
+ simplex= points;
+ else if (size < dim+1) {
+ fprintf (qh ferr, "qhull internal error (qh_voronoi_center):\n need at least %d points to construct a Voronoi center\n",
+ dim+1);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }else {
+ simplex= qh_settemp (dim+1);
+ qh_maxsimplex (dim, points, NULL, 0, &simplex);
+ }
+ point0= SETfirstt_(simplex, pointT);
+ gmcoord= qh gm_matrix;
+ for (k=0; k < dim; k++) {
+ qh gm_row[k]= gmcoord;
+ FOREACHpoint_(simplex) {
+ if (point != point0)
+ *(gmcoord++)= point[k] - point0[k];
+ }
+ }
+ sum2row= gmcoord;
+ for (i=0; i < dim; i++) {
+ sum2= 0.0;
+ for (k= 0; k < dim; k++) {
+ diffp= qh gm_row[k] + i;
+ sum2 += *diffp * *diffp;
+ }
+ *(gmcoord++)= sum2;
+ }
+ det= qh_determinant (qh gm_row, dim, &nearzero);
+ factor= qh_divzero (0.5, det, qh MINdenom, &infinite);
+ if (infinite) {
+ for (k=dim; k--; )
+ center[k]= qh_INFINITE;
+ if (qh IStracing)
+ qh_printpoints (qh ferr, "qh_voronoi_center: at infinity for ", simplex);
+ }else {
+ for (i=0; i < dim; i++) {
+ gmcoord= qh gm_matrix;
+ sum2p= sum2row;
+ for (k=0; k < dim; k++) {
+ qh gm_row[k]= gmcoord;
+ if (k == i) {
+ for (j= dim; j--; )
+ *(gmcoord++)= *sum2p++;
+ }else {
+ FOREACHpoint_(simplex) {
+ if (point != point0)
+ *(gmcoord++)= point[k] - point0[k];
+ }
+ }
+ }
+ center[i]= qh_determinant (qh gm_row, dim, &nearzero)*factor + point0[i];
+ }
+#ifndef qh_NOtrace
+ if (qh IStracing >= 3) {
+ fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+ qh_printmatrix (qh ferr, "center:", &center, 1, dim);
+ if (qh IStracing >= 5) {
+ qh_printpoints (qh ferr, "points", simplex);
+ FOREACHpoint_(simplex)
+ fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point),
+ qh_pointdist (point, center, dim));
+ fprintf (qh ferr, "\n");
+ }
+ }
+#endif
+ }
+ if (simplex != points)
+ qh_settempfree (&simplex);
+ return center;
+} /* voronoi_center */
+
diff --git a/extern/qhull/src/global.c b/extern/qhull/src/global.c
new file mode 100644
index 00000000000..d3e141aa985
--- /dev/null
+++ b/extern/qhull/src/global.c
@@ -0,0 +1,2018 @@
+/*<html><pre> -<a href="qh-globa.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ global.c
+ initializes all the globals of the qhull application
+
+ see README
+
+ see qhull.h for qh.globals and function prototypes
+
+ see qhull_a.h for internal functions
+
+ copyright (c) 1993-2002, The Geometry Center
+ */
+
+#include "qhull_a.h"
+
+/*========= qh definition =======================*/
+
+#if qh_QHpointer
+qhT *qh_qh= NULL; /* pointer to all global variables */
+#else
+qhT qh_qh; /* all global variables.
+ Add "= {0}" if this causes a compiler error.
+ Also qh_qhstat in stat.c and qhmem in mem.c. */
+#endif
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="appendprint">-</a>
+
+ qh_appendprint( printFormat )
+ append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint (qh_PRINT format) {
+ int i;
+
+ for (i=0; i < qh_PRINTEND; i++) {
+ if (qh PRINTout[i] == format && format != qh_PRINTqhull)
+ break;
+ if (!qh PRINTout[i]) {
+ qh PRINTout[i]= format;
+ break;
+ }
+ }
+} /* appendprint */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="checkflags">-</a>
+
+ qh_checkflags( commandStr, hiddenFlags )
+ errors if commandStr contains hiddenFlags
+ hiddenFlags starts and ends with a space and is space deliminated (checked)
+
+ notes:
+ ignores first word (e.g., "qconvex i")
+ use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+ see:
+ qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(char *command, char *hiddenflags) {
+ char *s= command, *t, *chkerr, key, opt, prevopt;
+ char chkkey[]= " ";
+ char chkopt[]= " ";
+ char chkopt2[]= " ";
+
+ if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+ fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (strpbrk(hiddenflags, ",\n\r\t")) {
+ fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ while (*s && !isspace(*s)) /* skip program name */
+ s++;
+ while (*s) {
+ while (*s && isspace(*s))
+ s++;
+ if (*s == '-')
+ s++;
+ if (!*s)
+ break;
+ key = *s++;
+ chkerr = NULL;
+ if (key == '\'') { /* TO 'file name' */
+ t= strchr(s, '\'');
+ if (!t) {
+ fprintf(qh ferr, "qhull error (qh_checkflags): missing the 2nd single-quote for:\n%s\n", s-1);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ s= t+1;
+ continue;
+ }
+ chkkey[1]= key;
+ if (strstr(hiddenflags, chkkey)) {
+ chkerr= chkkey;
+ }else if (isupper(key)) {
+ opt= ' ';
+ prevopt= ' ';
+ chkopt[1]= key;
+ chkopt2[1]= key;
+ while (!chkerr && *s && !isspace(*s)) {
+ opt= *s++;
+ if (isalpha(opt)) {
+ chkopt[2]= opt;
+ if (strstr(hiddenflags, chkopt))
+ chkerr= chkopt;
+ if (prevopt != ' ') {
+ chkopt2[2]= prevopt;
+ chkopt2[3]= opt;
+ if (strstr(hiddenflags, chkopt2))
+ chkerr= chkopt2;
+ }
+ }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
+ && (prevopt == ' ' || islower(prevopt))) {
+ chkopt[2]= opt;
+ if (strstr(hiddenflags, chkopt))
+ chkerr= chkopt;
+ }else {
+ qh_strtod (s-1, &t);
+ if (s < t)
+ s= t;
+ }
+ prevopt= opt;
+ }
+ }
+ if (chkerr) {
+ *chkerr= '\'';
+ chkerr[strlen(chkerr)-1]= '\'';
+ fprintf(qh ferr, "qhull error: option %s is not used with this program.\n It may be used with qhull.\n", chkerr);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ }
+} /* checkflags */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="clock">-</a>
+
+ qh_clock()
+ return user CPU time in 100ths (qh_SECtick)
+ only defined for qh_CLOCKtype == 2
+
+ notes:
+ use first value to determine time 0
+ from Stevens '92 8.15
+*/
+unsigned long qh_clock (void) {
+
+#if (qh_CLOCKtype == 2)
+ struct tms time;
+ static long clktck; /* initialized first call */
+ double ratio, cpu;
+ unsigned long ticks;
+
+ if (!clktck) {
+ if ((clktck= sysconf (_SC_CLK_TCK)) < 0) {
+ fprintf (qh ferr, "qhull internal error (qh_clock): sysconf() failed. Use qh_CLOCKtype 1 in user.h\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ }
+ if (times (&time) == -1) {
+ fprintf (qh ferr, "qhull internal error (qh_clock): times() failed. Use qh_CLOCKtype 1 in user.h\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ ratio= qh_SECticks / (double)clktck;
+ ticks= time.tms_utime * ratio;
+ return ticks;
+#else
+ fprintf (qh ferr, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL); /* never returns */
+ return 0;
+#endif
+} /* clock */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="freebuffers">-</a>
+
+ qh_freebuffers()
+ free up global memory buffers
+
+ notes:
+ must match qh_initbuffers()
+*/
+void qh_freebuffers (void) {
+
+ trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
+ /* allocated by qh_initqhull_buffers */
+ qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
+ qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
+ qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
+ qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
+ qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
+ qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+ qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
+ qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
+ qh lower_bound= qh upper_bound= NULL;
+ qh gm_matrix= NULL;
+ qh gm_row= NULL;
+ qh_setfree (&qh other_points);
+ qh_setfree (&qh del_vertices);
+ qh_setfree (&qh coplanarset);
+ if (qh line) /* allocated by qh_readinput, freed if no error */
+ free (qh line);
+ if (qh half_space)
+ free (qh half_space);
+ if (qh temp_malloc)
+ free (qh temp_malloc);
+ if (qh feasible_point) /* allocated by qh_readfeasible */
+ free (qh feasible_point);
+ if (qh feasible_string) /* allocated by qh_initflags */
+ free (qh feasible_string);
+ qh line= qh feasible_string= NULL;
+ qh half_space= qh feasible_point= qh temp_malloc= NULL;
+ /* usually allocated by qh_readinput */
+ if (qh first_point && qh POINTSmalloc) {
+ free(qh first_point);
+ qh first_point= NULL;
+ }
+ if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
+ free (qh input_points);
+ qh input_points= NULL;
+ }
+ trace5((qh ferr, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="freebuild">-</a>
+
+ qh_freebuild( allmem )
+ free global memory used by qh_initbuild and qh_buildhull
+ if !allmem,
+ does not free short memory (freed by qh_memfreeshort)
+
+ design:
+ free centrums
+ free each vertex
+ mark unattached ridges
+ for each facet
+ free ridges
+ free outside set, coplanar set, neighbor set, ridge set, vertex set
+ free facet
+ free hash table
+ free interior point
+ free merge set
+ free temporary sets
+*/
+void qh_freebuild (boolT allmem) {
+ facetT *facet;
+ vertexT *vertex;
+ ridgeT *ridge, **ridgep;
+ mergeT *merge, **mergep;
+
+ trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+ if (qh del_vertices)
+ qh_settruncate (qh del_vertices, 0);
+ if (allmem) {
+ qh_clearcenters (qh_ASnone);
+ while ((vertex= qh vertex_list)) {
+ if (vertex->next)
+ qh_delvertex (vertex);
+ else {
+ qh_memfree (vertex, sizeof(vertexT));
+ qh newvertex_list= qh vertex_list= NULL;
+ }
+ }
+ }else if (qh VERTEXneighbors) {
+ FORALLvertices
+ qh_setfreelong (&(vertex->neighbors));
+ }
+ qh VERTEXneighbors= False;
+ qh GOODclosest= NULL;
+ if (allmem) {
+ FORALLfacets {
+ FOREACHridge_(facet->ridges)
+ ridge->seen= False;
+ }
+ FORALLfacets {
+ if (facet->visible) {
+ FOREACHridge_(facet->ridges) {
+ if (!otherfacet_(ridge, facet)->visible)
+ ridge->seen= True; /* an unattached ridge */
+ }
+ }
+ }
+ while ((facet= qh facet_list)) {
+ FOREACHridge_(facet->ridges) {
+ if (ridge->seen) {
+ qh_setfree(&(ridge->vertices));
+ qh_memfree(ridge, sizeof(ridgeT));
+ }else
+ ridge->seen= True;
+ }
+ qh_setfree (&(facet->outsideset));
+ qh_setfree (&(facet->coplanarset));
+ qh_setfree (&(facet->neighbors));
+ qh_setfree (&(facet->ridges));
+ qh_setfree (&(facet->vertices));
+ if (facet->next)
+ qh_delfacet (facet);
+ else {
+ qh_memfree (facet, sizeof(facetT));
+ qh visible_list= qh newfacet_list= qh facet_list= NULL;
+ }
+ }
+ }else {
+ FORALLfacets {
+ qh_setfreelong (&(facet->outsideset));
+ qh_setfreelong (&(facet->coplanarset));
+ if (!facet->simplicial) {
+ qh_setfreelong (&(facet->neighbors));
+ qh_setfreelong (&(facet->ridges));
+ qh_setfreelong (&(facet->vertices));
+ }
+ }
+ }
+ qh_setfree (&(qh hash_table));
+ qh_memfree (qh interior_point, qh normal_size);
+ qh interior_point= NULL;
+ FOREACHmerge_(qh facet_mergeset) /* usually empty */
+ qh_memfree (merge, sizeof(mergeT));
+ qh facet_mergeset= NULL; /* temp set */
+ qh degen_mergeset= NULL; /* temp set */
+ qh_settempfree_all();
+} /* freebuild */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="freeqhull">-</a>
+
+ qh_freeqhull( allmem )
+ free global memory
+ if !allmem,
+ does not free short memory (freed by qh_memfreeshort)
+
+ notes:
+ sets qh.NOerrexit in case caller forgets to
+
+ design:
+ free global and temporary memory from qh_initbuild and qh_buildhull
+ free buffers
+ free statistics
+*/
+void qh_freeqhull (boolT allmem) {
+
+ trace1((qh ferr, "qh_freeqhull: free global memory\n"));
+ qh NOerrexit= True; /* no more setjmp since called at exit */
+ qh_freebuild (allmem);
+ qh_freebuffers();
+ qh_freestatistics();
+#if qh_QHpointer
+ free (qh_qh);
+ qh_qh= NULL;
+#else
+ memset((char *)&qh_qh, 0, sizeof(qhT));
+ qh NOerrexit= True;
+#endif
+} /* freeqhull */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="init_A">-</a>
+
+ qh_init_A( infile, outfile, errfile, argc, argv )
+ initialize memory and stdio files
+ convert input options to option string (qh.qhull_command)
+
+ notes:
+ infile may be NULL if qh_readpoints() is not called
+
+ errfile should always be defined. It is used for reporting
+ errors. outfile is used for output and format options.
+
+ argc/argv may be 0/NULL
+
+ called before error handling initialized
+ qh_errexit() may not be used
+*/
+void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+ qh_meminit (errfile);
+ qh_initqhull_start (infile, outfile, errfile);
+ qh_init_qhull_command (argc, argv);
+} /* init_A */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="init_B">-</a>
+
+ qh_init_B( points, numpoints, dim, ismalloc )
+ initialize globals for points array
+
+ points has numpoints dim-dimensional points
+ points[0] is the first coordinate of the first point
+ points[1] is the second coordinate of the first point
+ points[dim] is the first coordinate of the second point
+
+ ismalloc=True
+ Qhull will call free(points) on exit or input transformation
+ ismalloc=False
+ Qhull will allocate a new point array if needed for input transformation
+
+ qh.qhull_command
+ is the option string.
+ It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+ returns:
+ if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+ projects the input to a new point array
+
+ if qh.DELAUNAY,
+ qh.hull_dim is increased by one
+ if qh.ATinfinity,
+ qh_projectinput adds point-at-infinity for Delaunay tri.
+
+ if qh.SCALEinput
+ changes the upper and lower bounds of the input, see qh_scaleinput()
+
+ if qh.ROTATEinput
+ rotates the input by a random rotation, see qh_rotateinput()
+ if qh.DELAUNAY
+ rotates about the last coordinate
+
+ notes:
+ called after points are defined
+ qh_errexit() may be used
+*/
+void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
+ qh_initqhull_globals (points, numpoints, dim, ismalloc);
+ if (qhmem.LASTsize == 0)
+ qh_initqhull_mem();
+ /* mem.c and qset.c are initialized */
+ qh_initqhull_buffers();
+ qh_initthresholds (qh qhull_command);
+ if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
+ qh_projectinput();
+ if (qh SCALEinput)
+ qh_scaleinput();
+ if (qh ROTATErandom >= 0) {
+ qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
+ if (qh DELAUNAY) {
+ int k, lastk= qh hull_dim-1;
+ for (k= 0; k < lastk; k++) {
+ qh gm_row[k][lastk]= 0.0;
+ qh gm_row[lastk][k]= 0.0;
+ }
+ qh gm_row[lastk][lastk]= 1.0;
+ }
+ qh_gram_schmidt (qh hull_dim, qh gm_row);
+ qh_rotateinput (qh gm_row);
+ }
+} /* init_B */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="init_qhull_command">-</a>
+
+ qh_init_qhull_command( argc, argv )
+ build qh.qhull_command from argc/argv
+
+ returns:
+ a space-deliminated string of options (just as typed)
+
+ notes:
+ makes option string easy to input and output
+
+ argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(int argc, char *argv[]) {
+ int i;
+ char *s;
+
+ if (argc) {
+ if ((s= strrchr( argv[0], '\\'))) /* Borland gives full path */
+ strcpy (qh qhull_command, s+1);
+ else
+ strcpy (qh qhull_command, argv[0]);
+ if ((s= strstr (qh qhull_command, ".EXE"))
+ || (s= strstr (qh qhull_command, ".exe")))
+ *s= '\0';
+ }
+ for (i=1; i < argc; i++) {
+ if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
+ strcat (qh qhull_command, " ");
+ strcat (qh qhull_command, argv[i]);
+ }else {
+ fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
+ (int)sizeof(qh qhull_command));
+ exit (1); /* can not use qh_errexit */
+ }
+ }
+} /* init_qhull_command */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initflags">-</a>
+
+ qh_initflags( commandStr )
+ set flags and initialized constants from commandStr
+
+ returns:
+ sets qh.qhull_command to command if needed
+
+ notes:
+ ignores first word (e.g., "qhull d")
+ use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+ see:
+ qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+ 'prompt' in unix.c for documentation
+
+ design:
+ for each space-deliminated option group
+ if top-level option
+ check syntax
+ append approriate option to option string
+ set appropriate global variable or append printFormat to print options
+ else
+ for each sub-option
+ check syntax
+ append approriate option to option string
+ set appropriate global variable or append printFormat to print options
+
+
+*/
+void qh_initflags(char *command) {
+ int k, i, lastproject;
+ char *s= command, *t, *prev_s, *start, key;
+ boolT isgeom= False, wasproject;
+ realT r;
+
+ if (command != &qh qhull_command[0]) {
+ *qh qhull_command= '\0';
+ strncat( qh qhull_command, command, sizeof( qh qhull_command));
+ }
+ while (*s && !isspace(*s)) /* skip program name */
+ s++;
+ while (*s) {
+ while (*s && isspace(*s))
+ s++;
+ if (*s == '-')
+ s++;
+ if (!*s)
+ break;
+ prev_s= s;
+ switch (*s++) {
+ case 'd':
+ qh_option ("delaunay", NULL, NULL);
+ qh DELAUNAY= True;
+ break;
+ case 'f':
+ qh_option ("facets", NULL, NULL);
+ qh_appendprint (qh_PRINTfacets);
+ break;
+ case 'i':
+ qh_option ("incidence", NULL, NULL);
+ qh_appendprint (qh_PRINTincidences);
+ break;
+ case 'm':
+ qh_option ("mathematica", NULL, NULL);
+ qh_appendprint (qh_PRINTmathematica);
+ break;
+ case 'n':
+ qh_option ("normals", NULL, NULL);
+ qh_appendprint (qh_PRINTnormals);
+ break;
+ case 'o':
+ qh_option ("offFile", NULL, NULL);
+ qh_appendprint (qh_PRINToff);
+ break;
+ case 'p':
+ qh_option ("points", NULL, NULL);
+ qh_appendprint (qh_PRINTpoints);
+ break;
+ case 's':
+ qh_option ("summary", NULL, NULL);
+ qh PRINTsummary= True;
+ break;
+ case 'v':
+ qh_option ("voronoi", NULL, NULL);
+ qh VORONOI= True;
+ qh DELAUNAY= True;
+ break;
+ case 'A':
+ if (!isdigit(*s) && *s != '.' && *s != '-')
+ fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'. Ignored.\n");
+ else {
+ if (*s == '-') {
+ qh premerge_cos= -qh_strtod (s, &s);
+ qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
+ qh PREmerge= True;
+ }else {
+ qh postmerge_cos= qh_strtod (s, &s);
+ qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
+ qh POSTmerge= True;
+ }
+ qh MERGING= True;
+ }
+ break;
+ case 'C':
+ if (!isdigit(*s) && *s != '.' && *s != '-')
+ fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'. Ignored.\n");
+ else {
+ if (*s == '-') {
+ qh premerge_centrum= -qh_strtod (s, &s);
+ qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
+ qh PREmerge= True;
+ }else {
+ qh postmerge_centrum= qh_strtod (s, &s);
+ qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
+ qh POSTmerge= True;
+ }
+ qh MERGING= True;
+ }
+ break;
+ case 'E':
+ if (*s == '-')
+ fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'. Ignored.\n");
+ else if (!isdigit(*s))
+ fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'. Ignored.\n");
+ else {
+ qh DISTround= qh_strtod (s, &s);
+ qh_option ("Distance-roundoff", NULL, &qh DISTround);
+ qh SETroundoff= True;
+ }
+ break;
+ case 'H':
+ start= s;
+ qh HALFspace= True;
+ qh_strtod (s, &t);
+ while (t > s) {
+ if (*t && !isspace (*t)) {
+ if (*t == ',')
+ t++;
+ else
+ fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
+ }
+ s= t;
+ qh_strtod (s, &t);
+ }
+ if (start < t) {
+ if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
+ fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ strncpy (qh feasible_string, start, t-start);
+ qh_option ("Halfspace-about", NULL, NULL);
+ qh_option (qh feasible_string, NULL, NULL);
+ }else
+ qh_option ("Halfspace", NULL, NULL);
+ break;
+ case 'R':
+ if (!isdigit(*s))
+ fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'. Ignored\n");
+ else {
+ qh RANDOMfactor= qh_strtod (s, &s);
+ qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
+ qh RANDOMdist= True;
+ }
+ break;
+ case 'V':
+ if (!isdigit(*s) && *s != '-')
+ fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'. Ignored\n");
+ else {
+ qh MINvisible= qh_strtod (s, &s);
+ qh_option ("Visible", NULL, &qh MINvisible);
+ }
+ break;
+ case 'U':
+ if (!isdigit(*s) && *s != '-')
+ fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'. Ignored\n");
+ else {
+ qh MAXcoplanar= qh_strtod (s, &s);
+ qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
+ }
+ break;
+ case 'W':
+ if (*s == '-')
+ fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'. Ignored.\n");
+ else if (!isdigit(*s))
+ fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'. Ignored\n");
+ else {
+ qh MINoutside= qh_strtod (s, &s);
+ qh_option ("W-outside", NULL, &qh MINoutside);
+ qh APPROXhull= True;
+ }
+ break;
+ /************ sub menus ***************/
+ case 'F':
+ while (*s && !isspace(*s)) {
+ switch(*s++) {
+ case 'a':
+ qh_option ("Farea", NULL, NULL);
+ qh_appendprint (qh_PRINTarea);
+ qh GETarea= True;
+ break;
+ case 'A':
+ qh_option ("FArea-total", NULL, NULL);
+ qh GETarea= True;
+ break;
+ case 'c':
+ qh_option ("Fcoplanars", NULL, NULL);
+ qh_appendprint (qh_PRINTcoplanars);
+ break;
+ case 'C':
+ qh_option ("FCentrums", NULL, NULL);
+ qh_appendprint (qh_PRINTcentrums);
+ break;
+ case 'd':
+ qh_option ("Fd-cdd-in", NULL, NULL);
+ qh CDDinput= True;
+ break;
+ case 'D':
+ qh_option ("FD-cdd-out", NULL, NULL);
+ qh CDDoutput= True;
+ break;
+ case 'F':
+ qh_option ("FFacets-xridge", NULL, NULL);
+ qh_appendprint (qh_PRINTfacets_xridge);
+ break;
+ case 'i':
+ qh_option ("Finner", NULL, NULL);
+ qh_appendprint (qh_PRINTinner);
+ break;
+ case 'I':
+ qh_option ("FIDs", NULL, NULL);
+ qh_appendprint (qh_PRINTids);
+ break;
+ case 'm':
+ qh_option ("Fmerges", NULL, NULL);
+ qh_appendprint (qh_PRINTmerges);
+ break;
+ case 'n':
+ qh_option ("Fneighbors", NULL, NULL);
+ qh_appendprint (qh_PRINTneighbors);
+ break;
+ case 'N':
+ qh_option ("FNeighbors-vertex", NULL, NULL);
+ qh_appendprint (qh_PRINTvneighbors);
+ break;
+ case 'o':
+ qh_option ("Fouter", NULL, NULL);
+ qh_appendprint (qh_PRINTouter);
+ break;
+ case 'O':
+ if (qh PRINToptions1st) {
+ qh_option ("FOptions", NULL, NULL);
+ qh_appendprint (qh_PRINToptions);
+ }else
+ qh PRINToptions1st= True;
+ break;
+ case 'p':
+ qh_option ("Fpoint-intersect", NULL, NULL);
+ qh_appendprint (qh_PRINTpointintersect);
+ break;
+ case 'P':
+ qh_option ("FPoint-nearest", NULL, NULL);
+ qh_appendprint (qh_PRINTpointnearest);
+ break;
+ case 'Q':
+ qh_option ("FQhull", NULL, NULL);
+ qh_appendprint (qh_PRINTqhull);
+ break;
+ case 's':
+ qh_option ("Fsummary", NULL, NULL);
+ qh_appendprint (qh_PRINTsummary);
+ break;
+ case 'S':
+ qh_option ("FSize", NULL, NULL);
+ qh_appendprint (qh_PRINTsize);
+ qh GETarea= True;
+ break;
+ case 't':
+ qh_option ("Ftriangles", NULL, NULL);
+ qh_appendprint (qh_PRINTtriangles);
+ break;
+ case 'v':
+ /* option set in qh_initqhull_globals */
+ qh_appendprint (qh_PRINTvertices);
+ break;
+ case 'V':
+ qh_option ("FVertex-average", NULL, NULL);
+ qh_appendprint (qh_PRINTaverage);
+ break;
+ case 'x':
+ qh_option ("Fxtremes", NULL, NULL);
+ qh_appendprint (qh_PRINTextremes);
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ }
+ break;
+ case 'G':
+ isgeom= True;
+ qh_appendprint (qh_PRINTgeom);
+ while (*s && !isspace(*s)) {
+ switch(*s++) {
+ case 'a':
+ qh_option ("Gall-points", NULL, NULL);
+ qh PRINTdots= True;
+ break;
+ case 'c':
+ qh_option ("Gcentrums", NULL, NULL);
+ qh PRINTcentrums= True;
+ break;
+ case 'h':
+ qh_option ("Gintersections", NULL, NULL);
+ qh DOintersections= True;
+ break;
+ case 'i':
+ qh_option ("Ginner", NULL, NULL);
+ qh PRINTinner= True;
+ break;
+ case 'n':
+ qh_option ("Gno-planes", NULL, NULL);
+ qh PRINTnoplanes= True;
+ break;
+ case 'o':
+ qh_option ("Gouter", NULL, NULL);
+ qh PRINTouter= True;
+ break;
+ case 'p':
+ qh_option ("Gpoints", NULL, NULL);
+ qh PRINTcoplanar= True;
+ break;
+ case 'r':
+ qh_option ("Gridges", NULL, NULL);
+ qh PRINTridges= True;
+ break;
+ case 't':
+ qh_option ("Gtransparent", NULL, NULL);
+ qh PRINTtransparent= True;
+ break;
+ case 'v':
+ qh_option ("Gvertices", NULL, NULL);
+ qh PRINTspheres= True;
+ break;
+ case 'D':
+ if (!isdigit (*s))
+ fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
+ else {
+ if (qh DROPdim >= 0)
+ fprintf (qh ferr, "qhull warning: can only drop one dimension. Previous 'GD%d' ignored\n",
+ qh DROPdim);
+ qh DROPdim= qh_strtol (s, &s);
+ qh_option ("GDrop-dim", &qh DROPdim, NULL);
+ }
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ }
+ break;
+ case 'P':
+ while (*s && !isspace(*s)) {
+ switch(*s++) {
+ case 'd': case 'D': /* see qh_initthresholds() */
+ key= s[-1];
+ i= qh_strtol (s, &s);
+ r= 0;
+ if (*s == ':') {
+ s++;
+ r= qh_strtod (s, &s);
+ }
+ if (key == 'd')
+ qh_option ("Pdrop-facets-dim-less", &i, &r);
+ else
+ qh_option ("PDrop-facets-dim-more", &i, &r);
+ break;
+ case 'g':
+ qh_option ("Pgood-facets", NULL, NULL);
+ qh PRINTgood= True;
+ break;
+ case 'G':
+ qh_option ("PGood-facet-neighbors", NULL, NULL);
+ qh PRINTneighbors= True;
+ break;
+ case 'o':
+ qh_option ("Poutput-forced", NULL, NULL);
+ qh FORCEoutput= True;
+ break;
+ case 'p':
+ qh_option ("Pprecision-ignore", NULL, NULL);
+ qh PRINTprecision= False;
+ break;
+ case 'A':
+ if (!isdigit (*s))
+ fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
+ else {
+ qh KEEParea= qh_strtol (s, &s);
+ qh_option ("PArea-keep", &qh KEEParea, NULL);
+ qh GETarea= True;
+ }
+ break;
+ case 'F':
+ if (!isdigit (*s))
+ fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
+ else {
+ qh KEEPminArea= qh_strtod (s, &s);
+ qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
+ qh GETarea= True;
+ }
+ break;
+ case 'M':
+ if (!isdigit (*s))
+ fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
+ else {
+ qh KEEPmerge= qh_strtol (s, &s);
+ qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
+ }
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ }
+ break;
+ case 'Q':
+ lastproject= -1;
+ while (*s && !isspace(*s)) {
+ switch(*s++) {
+ case 'b': case 'B': /* handled by qh_initthresholds */
+ key= s[-1];
+ if (key == 'b' && *s == 'B') {
+ s++;
+ r= qh_DEFAULTbox;
+ qh SCALEinput= True;
+ qh_option ("QbBound-unit-box", NULL, &r);
+ break;
+ }
+ if (key == 'b' && *s == 'b') {
+ s++;
+ qh SCALElast= True;
+ qh_option ("Qbbound-last", NULL, NULL);
+ break;
+ }
+ k= qh_strtol (s, &s);
+ r= 0.0;
+ wasproject= False;
+ if (*s == ':') {
+ s++;
+ if ((r= qh_strtod(s, &s)) == 0.0) {
+ t= s; /* need true dimension for memory allocation */
+ while (*t && !isspace(*t)) {
+ if (toupper(*t++) == 'B'
+ && k == qh_strtol (t, &t)
+ && *t++ == ':'
+ && qh_strtod(t, &t) == 0.0) {
+ qh PROJECTinput++;
+ trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
+ qh_option ("Qb-project-dim", &k, NULL);
+ wasproject= True;
+ lastproject= k;
+ break;
+ }
+ }
+ }
+ }
+ if (!wasproject) {
+ if (lastproject == k && r == 0.0)
+ lastproject= -1; /* doesn't catch all possible sequences */
+ else if (key == 'b') {
+ qh SCALEinput= True;
+ if (r == 0.0)
+ r= -qh_DEFAULTbox;
+ qh_option ("Qbound-dim-low", &k, &r);
+ }else {
+ qh SCALEinput= True;
+ if (r == 0.0)
+ r= qh_DEFAULTbox;
+ qh_option ("QBound-dim-high", &k, &r);
+ }
+ }
+ break;
+ case 'c':
+ qh_option ("Qcoplanar-keep", NULL, NULL);
+ qh KEEPcoplanar= True;
+ break;
+ case 'f':
+ qh_option ("Qfurthest-outside", NULL, NULL);
+ qh BESToutside= True;
+ break;
+ case 'g':
+ qh_option ("Qgood-facets-only", NULL, NULL);
+ qh ONLYgood= True;
+ break;
+ case 'i':
+ qh_option ("Qinterior-keep", NULL, NULL);
+ qh KEEPinside= True;
+ break;
+ case 'm':
+ qh_option ("Qmax-outside-only", NULL, NULL);
+ qh ONLYmax= True;
+ break;
+ case 'r':
+ qh_option ("Qrandom-outside", NULL, NULL);
+ qh RANDOMoutside= True;
+ break;
+ case 's':
+ qh_option ("Qsearch-initial-simplex", NULL, NULL);
+ qh ALLpoints= True;
+ break;
+ case 't':
+ qh_option ("Qtriangulate", NULL, NULL);
+ qh TRIangulate= True;
+ break;
+ case 'T':
+ qh_option ("QTestPoints", NULL, NULL);
+ if (!isdigit (*s))
+ fprintf (qh ferr, "qhull input error: missing number of test points for option 'QTn'\n");
+ else {
+ qh TESTpoints= qh_strtol (s, &s);
+ qh_option ("QTestPoints", &qh TESTpoints, NULL);
+ }
+ break;
+ case 'u':
+ qh_option ("QupperDelaunay", NULL, NULL);
+ qh UPPERdelaunay= True;
+ break;
+ case 'v':
+ qh_option ("Qvertex-neighbors-convex", NULL, NULL);
+ qh TESTvneighbors= True;
+ break;
+ case 'x':
+ qh_option ("Qxact-merge", NULL, NULL);
+ qh MERGEexact= True;
+ break;
+ case 'z':
+ qh_option ("Qz-infinity-point", NULL, NULL);
+ qh ATinfinity= True;
+ break;
+ case '0':
+ qh_option ("Q0-no-premerge", NULL, NULL);
+ qh NOpremerge= True;
+ break;
+ case '1':
+ if (!isdigit(*s)) {
+ qh_option ("Q1-no-angle-sort", NULL, NULL);
+ qh ANGLEmerge= False;
+ break;
+ }
+ switch(*s++) {
+ case '0':
+ qh_option ("Q10-no-narrow", NULL, NULL);
+ qh NOnarrow= True;
+ break;
+ case '1':
+ qh_option ("Q11-trinormals Qtriangulate", NULL, NULL);
+ qh TRInormals= True;
+ qh TRIangulate= True;
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ break;
+ case '2':
+ qh_option ("Q2-no-merge-independent", NULL, NULL);
+ qh MERGEindependent= False;
+ goto LABELcheckdigit;
+ break; /* no warnings */
+ case '3':
+ qh_option ("Q3-no-merge-vertices", NULL, NULL);
+ qh MERGEvertices= False;
+ LABELcheckdigit:
+ if (isdigit(*s))
+ fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit. '%c' skipped.\n",
+ *s++);
+ break;
+ case '4':
+ qh_option ("Q4-avoid-old-into-new", NULL, NULL);
+ qh AVOIDold= True;
+ break;
+ case '5':
+ qh_option ("Q5-no-check-outer", NULL, NULL);
+ qh SKIPcheckmax= True;
+ break;
+ case '6':
+ qh_option ("Q6-no-concave-merge", NULL, NULL);
+ qh SKIPconvex= True;
+ break;
+ case '7':
+ qh_option ("Q7-no-breadth-first", NULL, NULL);
+ qh VIRTUALmemory= True;
+ break;
+ case '8':
+ qh_option ("Q8-no-near-inside", NULL, NULL);
+ qh NOnearinside= True;
+ break;
+ case '9':
+ qh_option ("Q9-pick-furthest", NULL, NULL);
+ qh PICKfurthest= True;
+ break;
+ case 'G':
+ i= qh_strtol (s, &t);
+ if (qh GOODpoint)
+ fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'. Ignored\n");
+ else if (s == t)
+ fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'. Ignored\n");
+ else if (i < 0 || *s == '-') {
+ qh GOODpoint= i-1;
+ qh_option ("QGood-if-dont-see-point", &i, NULL);
+ }else {
+ qh GOODpoint= i+1;
+ qh_option ("QGood-if-see-point", &i, NULL);
+ }
+ s= t;
+ break;
+ case 'J':
+ if (!isdigit(*s) && *s != '-')
+ qh JOGGLEmax= 0.0;
+ else {
+ qh JOGGLEmax= (realT) qh_strtod (s, &s);
+ qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+ }
+ break;
+ case 'R':
+ if (!isdigit(*s) && *s != '-')
+ fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'. Ignored\n");
+ else {
+ qh ROTATErandom= i= qh_strtol(s, &s);
+ if (i > 0)
+ qh_option ("QRotate-id", &i, NULL );
+ else if (i < -1)
+ qh_option ("QRandom-seed", &i, NULL );
+ }
+ break;
+ case 'V':
+ i= qh_strtol (s, &t);
+ if (qh GOODvertex)
+ fprintf (qh ferr, "qhull warning: good vertex already defined for option 'QVn'. Ignored\n");
+ else if (s == t)
+ fprintf (qh ferr, "qhull warning: no good point id given for option 'QVn'. Ignored\n");
+ else if (i < 0) {
+ qh GOODvertex= i - 1;
+ qh_option ("QV-good-facets-not-point", &i, NULL);
+ }else {
+ qh_option ("QV-good-facets-point", &i, NULL);
+ qh GOODvertex= i + 1;
+ }
+ s= t;
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ }
+ break;
+ case 'T':
+ while (*s && !isspace(*s)) {
+ if (isdigit(*s) || *s == '-')
+ qh IStracing= qh_strtol(s, &s);
+ else switch(*s++) {
+ case 'c':
+ qh_option ("Tcheck-frequently", NULL, NULL);
+ qh CHECKfrequently= True;
+ break;
+ case 's':
+ qh_option ("Tstatistics", NULL, NULL);
+ qh PRINTstatistics= True;
+ break;
+ case 'v':
+ qh_option ("Tverify", NULL, NULL);
+ qh VERIFYoutput= True;
+ break;
+ case 'z':
+ if (!qh fout)
+ fprintf (qh ferr, "qhull warning: output file undefined (stdout). Option 'Tz' ignored.\n");
+ else {
+ qh_option ("Tz-stdout", NULL, NULL);
+ qh ferr= qh fout;
+ qhmem.ferr= qh fout;
+ }
+ break;
+ case 'C':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing point id for cone for trace option 'TCn'. Ignored\n");
+ else {
+ i= qh_strtol (s, &s);
+ qh_option ("TCone-stop", &i, NULL);
+ qh STOPcone= i + 1;
+ }
+ break;
+ case 'F':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing frequency count for trace option 'TFn'. Ignored\n");
+ else {
+ qh REPORTfreq= qh_strtol (s, &s);
+ qh_option ("TFacet-log", &qh REPORTfreq, NULL);
+ qh REPORTfreq2= qh REPORTfreq/2; /* for tracemerging() */
+ }
+ break;
+ case 'I':
+ if (s[0] != ' ' || s[1] == '\"' || s[1] == '\'' ||isspace (s[1])) {
+ s++;
+ fprintf (qh ferr, "qhull warning: option 'TI' mistyped.\nUse 'TI', one space, file name, and space or end-of-line.\nDo not use quotes. Option 'FI' ignored.\n");
+ }else { /* not a procedure because of qh_option (filename, NULL, NULL); */
+ char filename[500], *t= filename;
+
+ s++;
+ while (*s) {
+ if (t - filename >= sizeof (filename)-2) {
+ fprintf (qh ferr, "qhull error: filename for 'TI' too long.\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (isspace (*s))
+ break;
+ *(t++)= *s++;
+ }
+ *t= '\0';
+ if (!freopen (filename, "r", stdin)) {
+ fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }else {
+ qh_option ("TInput-file", NULL, NULL);
+ qh_option (filename, NULL, NULL);
+ }
+ }
+ break;
+ case 'O':
+ if (s[0] != ' ' || s[1] == '\"' || isspace (s[1])) {
+ s++;
+ fprintf (qh ferr, "qhull warning: option 'TO' mistyped.\nUse 'TO', one space, file name, and space or end-of-line.\nThe file name may be enclosed in single quotes.\nDo not use double quotes. Option 'FO' ignored.\n");
+ }else { /* not a procedure because of qh_option (filename, NULL, NULL); */
+ char filename[500], *t= filename;
+ boolT isquote= False;
+
+ s++;
+ if (*s == '\'') {
+ isquote= True;
+ s++;
+ }
+ while (*s) {
+ if (t - filename >= sizeof (filename)-2) {
+ fprintf (qh ferr, "qhull error: filename for 'TO' too long.\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (isquote) {
+ if (*s == '\'') {
+ s++;
+ isquote= False;
+ break;
+ }
+ }else if (isspace (*s))
+ break;
+ *(t++)= *s++;
+ }
+ *t= '\0';
+ if (isquote)
+ fprintf (qh ferr, "qhull error: missing end quote for option 'TO'. Rest of line ignored.\n");
+ else if (!freopen (filename, "w", stdout)) {
+ fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }else {
+ qh_option ("TOutput-file", NULL, NULL);
+ qh_option (filename, NULL, NULL);
+ }
+ }
+ break;
+ case 'P':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing point id for trace option 'TPn'. Ignored\n");
+ else {
+ qh TRACEpoint= qh_strtol (s, &s);
+ qh_option ("Trace-point", &qh TRACEpoint, NULL);
+ }
+ break;
+ case 'M':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing merge id for trace option 'TMn'. Ignored\n");
+ else {
+ qh TRACEmerge= qh_strtol (s, &s);
+ qh_option ("Trace-merge", &qh TRACEmerge, NULL);
+ }
+ break;
+ case 'R':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing rerun count for trace option 'TRn'. Ignored\n");
+ else {
+ qh RERUN= qh_strtol (s, &s);
+ qh_option ("TRerun", &qh RERUN, NULL);
+ }
+ break;
+ case 'V':
+ i= qh_strtol (s, &t);
+ if (s == t)
+ fprintf (qh ferr, "qhull warning: missing furthest point id for trace option 'TVn'. Ignored\n");
+ else if (i < 0) {
+ qh STOPpoint= i - 1;
+ qh_option ("TV-stop-before-point", &i, NULL);
+ }else {
+ qh STOPpoint= i + 1;
+ qh_option ("TV-stop-after-point", &i, NULL);
+ }
+ s= t;
+ break;
+ case 'W':
+ if (!isdigit(*s))
+ fprintf (qh ferr, "qhull warning: missing max width for trace option 'TWn'. Ignored\n");
+ else {
+ qh TRACEdist= (realT) qh_strtod (s, &s);
+ qh_option ("TWide-trace", NULL, &qh TRACEdist);
+ }
+ break;
+ default:
+ s--;
+ fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
+ while (*++s && !isspace(*s));
+ break;
+ }
+ }
+ break;
+ default:
+ fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
+ (int)s[-1]);
+ break;
+ }
+ if (s-1 == prev_s && *s && !isspace(*s)) {
+ fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
+ (int)*prev_s, (int)*prev_s);
+ while (*s && !isspace(*s))
+ s++;
+ }
+ }
+ if (isgeom && !qh FORCEoutput && qh PRINTout[1])
+ fprintf (qh ferr, "qhull warning: additional output formats are not compatible with Geomview\n");
+ /* set derived values in qh_initqhull_globals */
+} /* initflags */
+
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initqhull_buffers">-</a>
+
+ qh_initqhull_buffers()
+ initialize global memory buffers
+
+ notes:
+ must match qh_freebuffers()
+*/
+void qh_initqhull_buffers (void) {
+ int k;
+
+ qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
+ if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
+ qh TEMPsize= 8; /* e.g., if qh_NOmem */
+ qh other_points= qh_setnew (qh TEMPsize);
+ qh del_vertices= qh_setnew (qh TEMPsize);
+ qh coplanarset= qh_setnew (qh TEMPsize);
+ qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
+ qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+ qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+ qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+ qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+ for(k= qh input_dim+1; k--; ) {
+ qh lower_threshold[k]= -REALmax;
+ qh upper_threshold[k]= REALmax;
+ qh lower_bound[k]= -REALmax;
+ qh upper_bound[k]= REALmax;
+ }
+ qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+ qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
+} /* initqhull_buffers */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initqhull_globals">-</a>
+
+ qh_initqhull_globals( points, numpoints, dim, ismalloc )
+ initialize globals
+ if ismalloc
+ points were malloc'd and qhull should free at end
+
+ returns:
+ sets qh.first_point, num_points, input_dim, hull_dim and others
+ seeds random number generator (seed=1 if tracing)
+ modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
+ adjust user flags as needed
+ also checks DIM3 dependencies and constants
+
+ notes:
+ do not use qh_point() since an input transformation may move them elsewhere
+
+ see:
+ qh_initqhull_start() sets default values for non-zero globals
+
+ design:
+ initialize points array from input arguments
+ test for qh.ZEROcentrum
+ (i.e., use opposite vertex instead of cetrum for convexity testing)
+ test for qh.PRINTgood (i.e., only print 'good' facets)
+ initialize qh.CENTERtype, qh.normal_size,
+ qh.center_size, qh.TRACEpoint/level,
+ initialize and test random numbers
+ check for conflicting print output options
+*/
+void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
+ int seed, pointsneeded, extra= 0, i, randi, k;
+ boolT printgeom= False, printmath= False, printcoplanar= False;
+ realT randr;
+ realT factorial;
+
+ time_t timedata;
+
+ trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
+ qh qhull_command));
+ qh POINTSmalloc= ismalloc;
+ qh first_point= points;
+ qh num_points= numpoints;
+ qh hull_dim= qh input_dim= dim;
+ if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
+ qh MERGING= True;
+ if (qh hull_dim <= 4) {
+ qh PREmerge= True;
+ qh_option ("_pre-merge", NULL, NULL);
+ }else {
+ qh MERGEexact= True;
+ qh_option ("Qxact_merge", NULL, NULL);
+ }
+ }else if (qh MERGEexact)
+ qh MERGING= True;
+ if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
+#ifdef qh_NOmerge
+ qh JOGGLEmax= 0.0;
+#endif
+ }
+ if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
+ fprintf(qh ferr, "qhull warning: joggle ('QJ') always produces simplicial output. Triangulated output ('Qt') does nothing.\n");
+ if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
+ qh SCALElast= True;
+ qh_option ("Qbbound-last-qj", NULL, NULL);
+ }
+ if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
+ && qh premerge_centrum == 0) {
+ qh ZEROcentrum= True;
+ qh ZEROall_ok= True;
+ qh_option ("_zero-centrum", NULL, NULL);
+ }
+ if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
+ fprintf(qh ferr, "qhull warning: real epsilon, %2.2g, is probably too large for joggle ('QJn')\nRecompile with double precision reals (see user.h).\n",
+ REALepsilon);
+#ifdef qh_NOmerge
+ if (qh MERGING) {
+ fprintf (qh ferr, "qhull input error: merging not installed (qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+#endif
+ if (!(qh PRINTgood || qh PRINTneighbors)) {
+ if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
+ || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
+ qh PRINTgood= True;
+ qh_option ("Pgood", NULL, NULL);
+ }
+ }
+ if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
+ qh KEEPinside= True;
+ qh_option ("Qinterior-keep", NULL, NULL);
+ }
+ if (qh DELAUNAY && qh HALFspace) {
+ fprintf (qh ferr, "qhull input error: can not use Delaunay ('d') or Voronoi ('v') with halfspace intersection ('H')\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
+ fprintf (qh ferr, "qhull input error: use upper-Delaunay ('Qu') or infinity-point ('Qz') with Delaunay ('d') or Voronoi ('v')\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh UPPERdelaunay && qh ATinfinity) {
+ fprintf (qh ferr, "qhull input error: can not use infinity-point ('Qz') with upper-Delaunay ('Qu')\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
+ fprintf (qh ferr, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
+ qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
+ qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
+ && !qh NOnearinside);
+ if (qh MERGING)
+ qh CENTERtype= qh_AScentrum;
+ else if (qh VORONOI)
+ qh CENTERtype= qh_ASvoronoi;
+ if (qh TESTvneighbors && !qh MERGING) {
+ fprintf(qh ferr, "qhull input error: test vertex neighbors ('Qv') needs a merge option\n");
+ qh_errexit (qh_ERRinput, NULL ,NULL);
+ }
+ if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
+ qh hull_dim -= qh PROJECTinput;
+ if (qh DELAUNAY) {
+ qh hull_dim++;
+ extra= 1;
+ }
+ }
+ if (qh hull_dim <= 1) {
+ fprintf(qh ferr, "qhull error: dimension %d must be > 1\n", qh hull_dim);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ for (k= 2, factorial=1.0; k < qh hull_dim; k++)
+ factorial *= k;
+ qh AREAfactor= 1.0 / factorial;
+ trace2((qh ferr, "qh_initqhull_globals: initialize globals. dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
+ dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
+ qh normal_size= qh hull_dim * sizeof(coordT);
+ qh center_size= qh normal_size - sizeof(coordT);
+ pointsneeded= qh hull_dim+1;
+ if (qh hull_dim > qh_DIMmergeVertex) {
+ qh MERGEvertices= False;
+ qh_option ("Q3-no-merge-vertices-dim-high", NULL, NULL);
+ }
+ if (qh GOODpoint)
+ pointsneeded++;
+#ifdef qh_NOtrace
+ if (qh IStracing) {
+ fprintf (qh ferr, "qhull input error: tracing is not installed (qh_NOtrace in user.h)");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+#endif
+ if (qh RERUN > 1) {
+ qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
+ if (qh IStracing != -1)
+ qh IStracing= 0;
+ }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+ qh TRACElevel= (qh IStracing? qh IStracing : 3);
+ qh IStracing= 0;
+ }
+ if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
+ seed= time (&timedata);
+ if (qh ROTATErandom == -1) {
+ seed= -seed;
+ qh_option ("QRandom-seed", &seed, NULL );
+ }else
+ qh_option ("QRotate-random", &seed, NULL);
+ qh ROTATErandom= seed;
+ }
+ seed= qh ROTATErandom;
+ if (seed == INT_MIN) /* default value */
+ seed= 1;
+ else if (seed < 0)
+ seed= -seed;
+ qh_RANDOMseed_(seed);
+ randr= 0.0;
+ for (i= 1000; i--; ) {
+ randi= qh_RANDOMint;
+ randr += randi;
+ if (randi > qh_RANDOMmax) {
+ fprintf (qh ferr, "\
+qhull configuration error (qh_RANDOMmax in user.h):\n\
+ random integer %d > qh_RANDOMmax (%.8g)\n",
+ randi, qh_RANDOMmax);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ }
+ qh_RANDOMseed_(seed);
+ randr = randr/1000;
+ if (randr < qh_RANDOMmax/10
+ || randr > qh_RANDOMmax * 5)
+ fprintf (qh ferr, "\
+qhull configuration warning (qh_RANDOMmax in user.h):\n\
+ average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
+ Is qh_RANDOMmax (%.2g) wrong?\n",
+ randr, qh_RANDOMmax/2.0, qh_RANDOMmax);
+ qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
+ qh RANDOMb= 1.0 - qh RANDOMfactor;
+ if (qh_HASHfactor < 1.1) {
+ fprintf(qh ferr, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
+ qh_HASHfactor);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ if (numpoints+extra < pointsneeded) {
+ fprintf(qh ferr,"qhull input error: not enough points (%d) to construct initial simplex (need %d)\n",
+ numpoints, pointsneeded);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (qh PRINTtransparent) {
+ if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
+ fprintf(qh ferr,"qhull input error: transparent Delaunay ('Gt') needs 3-d Delaunay ('d') w/o 'GDn'\n");
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ qh DROPdim = 3;
+ qh PRINTridges = True;
+ }
+ for (i= qh_PRINTEND; i--; ) {
+ if (qh PRINTout[i] == qh_PRINTgeom)
+ printgeom= True;
+ else if (qh PRINTout[i] == qh_PRINTmathematica)
+ printmath= True;
+ else if (qh PRINTout[i] == qh_PRINTcoplanars)
+ printcoplanar= True;
+ else if (qh PRINTout[i] == qh_PRINTpointnearest)
+ printcoplanar= True;
+ else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
+ fprintf (qh ferr, "qhull input error: option 'Fp' is only used for \nhalfspace intersection ('Hn,n,n').\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
+ fprintf (qh ferr, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
+ fprintf (qh ferr, "qhull input error: option 'FC' is not available for Voronoi vertices ('v')\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }else if (qh PRINTout[i] == qh_PRINTvertices) {
+ if (qh VORONOI)
+ qh_option ("Fvoronoi", NULL, NULL);
+ else
+ qh_option ("Fvertices", NULL, NULL);
+ }
+ }
+ if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
+ if (qh PRINTprecision)
+ fprintf (qh ferr, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
+ }
+ if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
+ if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
+ qh KEEPcoplanar = True;
+ qh_option ("Qcoplanar", NULL, NULL);
+ }
+ }
+ if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
+ fprintf (qh ferr, "qhull input error: Mathematica output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (printgeom) {
+ if (qh hull_dim > 4) {
+ fprintf (qh ferr, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
+ + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
+ fprintf (qh ferr, "qhull input error: no output specified for Geomview\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
+ fprintf (qh ferr, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ /* can not warn about furthest-site Geomview output: no lower_threshold */
+ if (qh hull_dim == 4 && qh DROPdim == -1 &&
+ (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+ fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\
+available for 4-d output (ignored). Could use 'GDn' instead.\n");
+ qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
+ }
+ }
+ qh PRINTdim= qh hull_dim;
+ if (qh DROPdim >=0) { /* after Geomview checks */
+ if (qh DROPdim < qh hull_dim) {
+ qh PRINTdim--;
+ if (!printgeom || qh hull_dim < 3)
+ fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
+ }else
+ qh DROPdim= -1;
+ }else if (qh VORONOI) {
+ qh DROPdim= qh hull_dim-1;
+ qh PRINTdim= qh hull_dim-1;
+ }
+} /* initqhull_globals */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initqhull_mem">-</a>
+
+ qh_initqhull_mem( )
+ initialize mem.c for qhull
+ qh.hull_dim and qh.normal_size determine some of the allocation sizes
+ if qh.MERGING,
+ includes ridgeT
+ calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
+ (see numsizes below)
+
+ returns:
+ mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
+
+ notes:
+ qh_produceoutput() prints memsizes
+
+*/
+void qh_initqhull_mem (void) {
+ int numsizes;
+ int i;
+
+ numsizes= 8+10;
+ qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes,
+ qh_MEMbufsize,qh_MEMinitbuf);
+ qh_memsize(sizeof(vertexT));
+ if (qh MERGING) {
+ qh_memsize(sizeof(ridgeT));
+ qh_memsize(sizeof(mergeT));
+ }
+ qh_memsize(sizeof(facetT));
+ i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize; /* ridge.vertices */
+ qh_memsize(i);
+ qh_memsize(qh normal_size); /* normal */
+ i += SETelemsize; /* facet.vertices, .ridges, .neighbors */
+ qh_memsize(i);
+ qh_user_memsizes();
+ qh_memsetup();
+} /* initqhull_mem */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initqhull_start">-</a>
+
+ qh_initqhull_start( infile, outfile, errfile )
+ start initialization of qhull
+ initialize statistics, stdio, default values for global variables
+
+ see:
+ qh_maxmin() determines the precision constants
+*/
+void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) {
+
+ qh_CPUclock; /* start the clock */
+#if qh_QHpointer
+ if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) {
+ fprintf (errfile, "qhull error (qh_initqhull_globals): insufficient memory\n");
+ exit (qh_ERRmem); /* no error handler */
+ }
+ memset((char *)qh_qh, 0, sizeof(qhT)); /* every field is 0, FALSE, NULL */
+#else
+ memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+ strcat (qh qhull, "qhull");
+ qh_initstatistics();
+ qh ANGLEmerge= True;
+ qh DROPdim= -1;
+ qh ferr= errfile;
+ qh fin= infile;
+ qh fout= outfile;
+ qh furthest_id= -1;
+ qh JOGGLEmax= REALmax;
+ qh KEEPminArea = REALmax;
+ qh last_low= REALmax;
+ qh last_high= REALmax;
+ qh last_newhigh= REALmax;
+ qh max_outside= 0.0;
+ qh max_vertex= 0.0;
+ qh MAXabs_coord= 0.0;
+ qh MAXsumcoord= 0.0;
+ qh MAXwidth= -REALmax;
+ qh MERGEindependent= True;
+ qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
+ qh MINoutside= 0.0;
+ qh MINvisible= REALmax;
+ qh MAXcoplanar= REALmax;
+ qh outside_err= REALmax;
+ qh premerge_centrum= 0.0;
+ qh premerge_cos= REALmax;
+ qh PRINTprecision= True;
+ qh PRINTradius= 0.0;
+ qh postmerge_cos= REALmax;
+ qh postmerge_centrum= 0.0;
+ qh ROTATErandom= INT_MIN;
+ qh MERGEvertices= True;
+ qh totarea= 0.0;
+ qh totvol= 0.0;
+ qh TRACEdist= REALmax;
+ qh TRACEpoint= -1; /* recompile or use 'TPn' */
+ qh tracefacet_id= UINT_MAX; /* recompile to trace a facet */
+ qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
+ qh_RANDOMseed_(1);
+} /* initqhull_start */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="initthresholds">-</a>
+
+ qh_initthresholds( commandString )
+ set thresholds for printing and scaling from commandString
+
+ returns:
+ sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
+
+ see:
+ qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
+ qh_inthresholds()
+
+ design:
+ for each 'Pdn' or 'PDn' option
+ check syntax
+ set qh.lower_threshold or qh.upper_threshold
+ set qh.GOODthreshold if an unbounded threshold is used
+ set qh.SPLITthreshold if a bounded threshold is used
+*/
+void qh_initthresholds(char *command) {
+ realT value;
+ int index, maxdim, k;
+ char *s= command;
+ char key;
+
+ maxdim= qh input_dim;
+ if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
+ maxdim++;
+ while (*s) {
+ if (*s == '-')
+ s++;
+ if (*s == 'P') {
+ s++;
+ while (*s && !isspace(key= *s++)) {
+ if (key == 'd' || key == 'D') {
+ if (!isdigit(*s)) {
+ fprintf(qh ferr, "qhull warning: no dimension given for Print option '%c' at: %s. Ignored\n",
+ key, s-1);
+ continue;
+ }
+ index= qh_strtol (s, &s);
+ if (index >= qh hull_dim) {
+ fprintf(qh ferr, "qhull warning: dimension %d for Print option '%c' is >= %d. Ignored\n",
+ index, key, qh hull_dim);
+ continue;
+ }
+ if (*s == ':') {
+ s++;
+ value= qh_strtod(s, &s);
+ if (fabs((double)value) > 1.0) {
+ fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1. Ignored\n",
+ value, key);
+ continue;
+ }
+ }else
+ value= 0.0;
+ if (key == 'd')
+ qh lower_threshold[index]= value;
+ else
+ qh upper_threshold[index]= value;
+ }
+ }
+ }else if (*s == 'Q') {
+ s++;
+ while (*s && !isspace(key= *s++)) {
+ if (key == 'b' && *s == 'B') {
+ s++;
+ for (k=maxdim; k--; ) {
+ qh lower_bound[k]= -qh_DEFAULTbox;
+ qh upper_bound[k]= qh_DEFAULTbox;
+ }
+ }else if (key == 'b' && *s == 'b')
+ s++;
+ else if (key == 'b' || key == 'B') {
+ if (!isdigit(*s)) {
+ fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c. Ignored\n",
+ key);
+ continue;
+ }
+ index= qh_strtol (s, &s);
+ if (index >= maxdim) {
+ fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d. Ignored\n",
+ index, key, maxdim);
+ continue;
+ }
+ if (*s == ':') {
+ s++;
+ value= qh_strtod(s, &s);
+ }else if (key == 'b')
+ value= -qh_DEFAULTbox;
+ else
+ value= qh_DEFAULTbox;
+ if (key == 'b')
+ qh lower_bound[index]= value;
+ else
+ qh upper_bound[index]= value;
+ }
+ }
+ }else {
+ while (*s && !isspace (*s))
+ s++;
+ }
+ while (isspace (*s))
+ s++;
+ }
+ for (k= qh hull_dim; k--; ) {
+ if (qh lower_threshold[k] > -REALmax/2) {
+ qh GOODthreshold= True;
+ if (qh upper_threshold[k] < REALmax/2) {
+ qh SPLITthresholds= True;
+ qh GOODthreshold= False;
+ break;
+ }
+ }else if (qh upper_threshold[k] < REALmax/2)
+ qh GOODthreshold= True;
+ }
+} /* initthresholds */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="option">-</a>
+
+ qh_option( option, intVal, realVal )
+ add an option description to qh.qhull_options
+
+ notes:
+ will be printed with statistics ('Ts') and errors
+ strlen(option) < 40
+*/
+void qh_option (char *option, int *i, realT *r) {
+ char buf[200];
+ int len, maxlen;
+
+ sprintf (buf, " %s", option);
+ if (i)
+ sprintf (buf+strlen(buf), " %d", *i);
+ if (r)
+ sprintf (buf+strlen(buf), " %2.2g", *r);
+ len= strlen(buf);
+ qh qhull_optionlen += len;
+ maxlen= sizeof (qh qhull_options) - len -1;
+ maximize_(maxlen, 0);
+ if (qh qhull_optionlen >= 80 && maxlen > 0) {
+ qh qhull_optionlen= len;
+ strncat (qh qhull_options, "\n", maxlen--);
+ }
+ strncat (qh qhull_options, buf, maxlen);
+} /* option */
+
+#if qh_QHpointer
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="restore_qhull">-</a>
+
+ qh_restore_qhull( oldqh )
+ restores a previously saved qhull
+ also restores qh_qhstat and qhmem.tempstack
+
+ notes:
+ errors if current qhull hasn't been saved or freed
+ uses qhmem for error reporting
+
+ NOTE 1998/5/11:
+ Freeing memory after qh_save_qhull and qh_restore_qhull
+ is complicated. The procedures will be redesigned.
+
+ see:
+ qh_save_qhull()
+*/
+void qh_restore_qhull (qhT **oldqh) {
+
+ if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
+ *oldqh);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ if (qh_qh) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ if (!*oldqh || !(*oldqh)->old_qhstat) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
+ *oldqh);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh_qh= *oldqh;
+ *oldqh= NULL;
+ qh_qhstat= qh old_qhstat;
+ qhmem.tempstack= qh old_tempstack;
+ trace1((qh ferr, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
+} /* restore_qhull */
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="save_qhull">-</a>
+
+ qh_save_qhull( )
+ saves qhull for a later qh_restore_qhull
+ also saves qh_qhstat and qhmem.tempstack
+
+ returns:
+ qh_qh=NULL
+
+ notes:
+ need to initialize qhull or call qh_restore_qhull before continuing
+
+ NOTE 1998/5/11:
+ Freeing memory after qh_save_qhull and qh_restore_qhull
+ is complicated. The procedures will be redesigned.
+
+ see:
+ qh_restore_qhull()
+*/
+qhT *qh_save_qhull (void) {
+ qhT *oldqh;
+
+ trace1((qhmem.ferr, "qh_save_qhull: save qhull %p\n", qh_qh));
+ if (!qh_qh) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_save_qhull): qhull not initialized\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh old_qhstat= qh_qhstat;
+ qh_qhstat= NULL;
+ qh old_tempstack= qhmem.tempstack;
+ qhmem.tempstack= NULL;
+ oldqh= qh_qh;
+ qh_qh= NULL;
+ return oldqh;
+} /* save_qhull */
+
+#endif
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="strtol">-</a>
+
+ qh_strtol( s, endp) qh_strtod( s, endp)
+ internal versions of strtol() and strtod()
+ does not skip trailing spaces
+ notes:
+ some implementations of strtol()/strtod() skip trailing spaces
+*/
+double qh_strtod (const char *s, char **endp) {
+ double result;
+
+ result= strtod (s, endp);
+ if (s < (*endp) && (*endp)[-1] == ' ')
+ (*endp)--;
+ return result;
+} /* strtod */
+
+int qh_strtol (const char *s, char **endp) {
+ int result;
+
+ result= (int) strtol (s, endp, 10);
+ if (s< (*endp) && (*endp)[-1] == ' ')
+ (*endp)--;
+ return result;
+} /* strtol */
diff --git a/extern/qhull/src/io.c b/extern/qhull/src/io.c
new file mode 100644
index 00000000000..9b0ccdd0b24
--- /dev/null
+++ b/extern/qhull/src/io.c
@@ -0,0 +1,4089 @@
+/*<html><pre> -<a href="qh-io.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ io.c
+ Input/Output routines of qhull application
+
+ see qh-io.htm and io.h
+
+ see user.c for qh_errprint and qh_printfacetlist
+
+ unix.c calls qh_readpoints and qh_produce_output
+
+ unix.c and user.c are the only callers of io.c functions
+ This allows the user to avoid loading io.o from qhull.a
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*========= -prototypes for internal functions ========= */
+
+static int qh_compare_facetarea(const void *p1, const void *p2);
+static int qh_compare_facetmerge(const void *p1, const void *p2);
+static int qh_compare_facetvisit(const void *p1, const void *p2);
+int qh_compare_vertexpoint(const void *p1, const void *p2); /* not used */
+
+/*========= -functions in alphabetical order after qh_produce_output() =====*/
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="produce_output">-</a>
+
+ qh_produce_output()
+ prints out the result of qhull in desired format
+ if qh.GETarea
+ computes and prints area and volume
+ qh.PRINTout[] is an array of output formats
+
+ notes:
+ prints output in qh.PRINTout order
+*/
+void qh_produce_output(void) {
+ int i, tempsize= qh_setsize ((setT*)qhmem.tempstack), d_1;
+
+ if (qh VORONOI) {
+ qh_clearcenters (qh_ASvoronoi);
+ qh_vertexneighbors();
+ }
+ if (qh TRIangulate) {
+ qh_triangulate();
+ if (qh VERIFYoutput && !qh CHECKfrequently)
+ qh_checkpolygon (qh facet_list);
+ }
+ qh_findgood_all (qh facet_list);
+ if (qh GETarea)
+ qh_getarea(qh facet_list);
+ if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
+ qh_markkeep (qh facet_list);
+ if (qh PRINTsummary)
+ qh_printsummary(qh ferr);
+ else if (qh PRINTout[0] == qh_PRINTnone)
+ qh_printsummary(qh fout);
+ for (i= 0; i < qh_PRINTEND; i++)
+ qh_printfacets (qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
+ qh_allstatistics();
+ if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
+ qh_printstats (qh ferr, qhstat precision, NULL);
+ if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
+ qh_printstats (qh ferr, qhstat vridges, NULL);
+ if (qh PRINTstatistics) {
+ qh_collectstatistics();
+ qh_printstatistics(qh ferr, "");
+ qh_memstatistics (qh ferr);
+ d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
+ fprintf(qh ferr, "\
+ size in bytes: merge %ld ridge %ld vertex %ld facet %ld\n\
+ normal %d ridge vertices %d facet vertices or neighbors %ld\n",
+ sizeof(mergeT), sizeof(ridgeT),
+ sizeof(vertexT), sizeof(facetT),
+ qh normal_size, d_1, d_1 + SETelemsize);
+ }
+ if (qh_setsize ((setT*)qhmem.tempstack) != tempsize) {
+ fprintf (qh ferr, "qhull internal error (qh_produce_output): temporary sets not empty (%d)\n",
+ qh_setsize ((setT*)qhmem.tempstack));
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+} /* produce_output */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="dfacet">-</a>
+
+ dfacet( id )
+ print facet by id, for debugging
+
+*/
+void dfacet (unsigned id) {
+ facetT *facet;
+
+ FORALLfacets {
+ if (facet->id == id) {
+ qh_printfacet (qh fout, facet);
+ break;
+ }
+ }
+} /* dfacet */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="dvertex">-</a>
+
+ dvertex( id )
+ print vertex by id, for debugging
+*/
+void dvertex (unsigned id) {
+ vertexT *vertex;
+
+ FORALLvertices {
+ if (vertex->id == id) {
+ qh_printvertex (qh fout, vertex);
+ break;
+ }
+ }
+} /* dvertex */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="compare_vertexpoint">-</a>
+
+ qh_compare_vertexpoint( p1, p2 )
+ used by qsort() to order vertices by point id
+*/
+int qh_compare_vertexpoint(const void *p1, const void *p2) {
+ vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
+
+ return ((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
+} /* compare_vertexpoint */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="compare_facetarea">-</a>
+
+ qh_compare_facetarea( p1, p2 )
+ used by qsort() to order facets by area
+*/
+static int qh_compare_facetarea(const void *p1, const void *p2) {
+ facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+
+ if (!a->isarea)
+ return -1;
+ if (!b->isarea)
+ return 1;
+ if (a->f.area > b->f.area)
+ return 1;
+ else if (a->f.area == b->f.area)
+ return 0;
+ return -1;
+} /* compare_facetarea */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="compare_facetmerge">-</a>
+
+ qh_compare_facetmerge( p1, p2 )
+ used by qsort() to order facets by number of merges
+*/
+static int qh_compare_facetmerge(const void *p1, const void *p2) {
+ facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+
+ return (a->nummerge - b->nummerge);
+} /* compare_facetvisit */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="compare_facetvisit">-</a>
+
+ qh_compare_facetvisit( p1, p2 )
+ used by qsort() to order facets by visit id or id
+*/
+static int qh_compare_facetvisit(const void *p1, const void *p2) {
+ facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+ int i,j;
+
+ if (!(i= a->visitid))
+ i= - a->id; /* do not convert to int */
+ if (!(j= b->visitid))
+ j= - b->id;
+ return (i - j);
+} /* compare_facetvisit */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="countfacets">-</a>
+
+ qh_countfacets( facetlist, facets, printall,
+ numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars )
+ count good facets for printing and set visitid
+ if allfacets, ignores qh_skipfacet()
+
+ notes:
+ qh_printsummary and qh_countfacets must match counts
+
+ returns:
+ numfacets, numsimplicial, total neighbors, numridges, coplanars
+ each facet with ->visitid indicating 1-relative position
+ ->visitid==0 indicates not good
+
+ notes
+ numfacets >= numsimplicial
+ if qh.NEWfacets,
+ does not count visible facets (matches qh_printafacet)
+
+ design:
+ for all facets on facetlist and in facets set
+ unless facet is skipped or visible (i.e., will be deleted)
+ mark facet->visitid
+ update counts
+*/
+void qh_countfacets (facetT *facetlist, setT *facets, boolT printall,
+ int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
+ facetT *facet, **facetp;
+ int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
+
+ FORALLfacet_(facetlist) {
+ if ((facet->visible && qh NEWfacets)
+ || (!printall && qh_skipfacet(facet)))
+ facet->visitid= 0;
+ else {
+ facet->visitid= ++numfacets;
+ totneighbors += qh_setsize (facet->neighbors);
+ if (facet->simplicial) {
+ numsimplicial++;
+ if (facet->keepcentrum && facet->tricoplanar)
+ numtricoplanars++;
+ }else
+ numridges += qh_setsize (facet->ridges);
+ if (facet->coplanarset)
+ numcoplanars += qh_setsize (facet->coplanarset);
+ }
+ }
+ FOREACHfacet_(facets) {
+ if ((facet->visible && qh NEWfacets)
+ || (!printall && qh_skipfacet(facet)))
+ facet->visitid= 0;
+ else {
+ facet->visitid= ++numfacets;
+ totneighbors += qh_setsize (facet->neighbors);
+ if (facet->simplicial){
+ numsimplicial++;
+ if (facet->keepcentrum && facet->tricoplanar)
+ numtricoplanars++;
+ }else
+ numridges += qh_setsize (facet->ridges);
+ if (facet->coplanarset)
+ numcoplanars += qh_setsize (facet->coplanarset);
+ }
+ }
+ qh visit_id += numfacets+1;
+ *numfacetsp= numfacets;
+ *numsimplicialp= numsimplicial;
+ *totneighborsp= totneighbors;
+ *numridgesp= numridges;
+ *numcoplanarsp= numcoplanars;
+ *numtricoplanarsp= numtricoplanars;
+} /* countfacets */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="detvnorm">-</a>
+
+ qh_detvnorm( vertex, vertexA, centers, offset )
+ compute separating plane of the Voronoi diagram for a pair of input sites
+ centers= set of facets (i.e., Voronoi vertices)
+ facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+
+ assumes:
+ qh_ASvoronoi and qh_vertexneighbors() already set
+
+ returns:
+ norm
+ a pointer into qh.gm_matrix to qh.hull_dim-1 reals
+ copy the data before reusing qh.gm_matrix
+ offset
+ if 'QVn'
+ sign adjusted so that qh.GOODvertexp is inside
+ else
+ sign adjusted so that vertex is inside
+
+ qh.gm_matrix= simplex of points from centers relative to first center
+
+ notes:
+ in io.c so that code for 'v Tv' can be removed by removing io.c
+ returns pointer into qh.gm_matrix to avoid tracking of temporary memory
+
+ design:
+ determine midpoint of input sites
+ build points as the set of Voronoi vertices
+ select a simplex from points (if necessary)
+ include midpoint if the Voronoi region is unbounded
+ relocate the first vertex of the simplex to the origin
+ compute the normalized hyperplane through the simplex
+ orient the hyperplane toward 'QVn' or 'vertex'
+ if 'Tv' or 'Ts'
+ if bounded
+ test that hyperplane is the perpendicular bisector of the input sites
+ test that Voronoi vertices not in the simplex are still on the hyperplane
+ free up temporary memory
+*/
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
+ facetT *facet, **facetp;
+ int i, k, pointid, pointidA, point_i, point_n;
+ setT *simplex= NULL;
+ pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
+ coordT *coord, *gmcoord, *normalp;
+ setT *points= qh_settemp (qh TEMPsize);
+ boolT nearzero= False;
+ boolT unbounded= False;
+ int numcenters= 0;
+ int dim= qh hull_dim - 1;
+ realT dist, offset, angle, zero= 0.0;
+
+ midpoint= qh gm_matrix + qh hull_dim * qh hull_dim; /* last row */
+ for (k= 0; k < dim; k++)
+ midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
+ FOREACHfacet_(centers) {
+ numcenters++;
+ if (!facet->visitid)
+ unbounded= True;
+ else {
+ if (!facet->center)
+ facet->center= qh_facetcenter (facet->vertices);
+ qh_setappend (&points, facet->center);
+ }
+ }
+ if (numcenters > dim) {
+ simplex= qh_settemp (qh TEMPsize);
+ qh_setappend (&simplex, vertex->point);
+ if (unbounded)
+ qh_setappend (&simplex, midpoint);
+ qh_maxsimplex (dim, points, NULL, 0, &simplex);
+ qh_setdelnth (simplex, 0);
+ }else if (numcenters == dim) {
+ if (unbounded)
+ qh_setappend (&points, midpoint);
+ simplex= points;
+ }else {
+ fprintf(qh ferr, "qh_detvnorm: too few points (%d) to compute separating plane\n", numcenters);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ i= 0;
+ gmcoord= qh gm_matrix;
+ point0= SETfirstt_(simplex, pointT);
+ FOREACHpoint_(simplex) {
+ if (qh IStracing >= 4)
+ qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
+ &point, 1, dim);
+ if (point != point0) {
+ qh gm_row[i++]= gmcoord;
+ coord= point0;
+ for (k= dim; k--; )
+ *(gmcoord++)= *point++ - *coord++;
+ }
+ }
+ qh gm_row[i]= gmcoord; /* does not overlap midpoint, may be used later for qh_areasimplex */
+ normal= gmcoord;
+ qh_sethyperplane_gauss (dim, qh gm_row, point0, True,
+ normal, &offset, &nearzero);
+ if (qh GOODvertexp == vertexA->point)
+ inpoint= vertexA->point;
+ else
+ inpoint= vertex->point;
+ zinc_(Zdistio);
+ dist= qh_distnorm (dim, inpoint, normal, &offset);
+ if (dist > 0) {
+ offset= -offset;
+ normalp= normal;
+ for (k= dim; k--; ) {
+ *normalp= -(*normalp);
+ normalp++;
+ }
+ }
+ if (qh VERIFYoutput || qh PRINTstatistics) {
+ pointid= qh_pointid (vertex->point);
+ pointidA= qh_pointid (vertexA->point);
+ if (!unbounded) {
+ zinc_(Zdiststat);
+ dist= qh_distnorm (dim, midpoint, normal, &offset);
+ if (dist < 0)
+ dist= -dist;
+ zzinc_(Zridgemid);
+ wwmax_(Wridgemidmax, dist);
+ wwadd_(Wridgemid, dist);
+ trace4((qh ferr, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
+ pointid, pointidA, dist));
+ for (k= 0; k < dim; k++)
+ midpoint[k]= vertexA->point[k] - vertex->point[k]; /* overwrites midpoint! */
+ qh_normalize (midpoint, dim, False);
+ angle= qh_distnorm (dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
+ if (angle < 0.0)
+ angle= angle + 1.0;
+ else
+ angle= angle - 1.0;
+ if (angle < 0.0)
+ angle -= angle;
+ trace4((qh ferr, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
+ pointid, pointidA, angle, nearzero));
+ if (nearzero) {
+ zzinc_(Zridge0);
+ wwmax_(Wridge0max, angle);
+ wwadd_(Wridge0, angle);
+ }else {
+ zzinc_(Zridgeok)
+ wwmax_(Wridgeokmax, angle);
+ wwadd_(Wridgeok, angle);
+ }
+ }
+ if (simplex != points) {
+ FOREACHpoint_i_(points) {
+ if (!qh_setin (simplex, point)) {
+ facet= SETelemt_(centers, point_i, facetT);
+ zinc_(Zdiststat);
+ dist= qh_distnorm (dim, point, normal, &offset);
+ if (dist < 0)
+ dist= -dist;
+ zzinc_(Zridge);
+ wwmax_(Wridgemax, dist);
+ wwadd_(Wridge, dist);
+ trace4((qh ferr, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
+ pointid, pointidA, facet->visitid, dist));
+ }
+ }
+ }
+ }
+ *offsetp= offset;
+ if (simplex != points)
+ qh_settempfree (&simplex);
+ qh_settempfree (&points);
+ return normal;
+} /* detvnorm */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="detvridge">-</a>
+
+ qh_detvridge( vertexA )
+ determine Voronoi ridge from 'seen' neighbors of vertexA
+ include one vertex-at-infinite if an !neighbor->visitid
+
+ returns:
+ temporary set of centers (facets, i.e., Voronoi vertices)
+ sorted by center id
+*/
+setT *qh_detvridge (vertexT *vertex) {
+ setT *centers= qh_settemp (qh TEMPsize);
+ setT *tricenters= qh_settemp (qh TEMPsize);
+ facetT *neighbor, **neighborp;
+ boolT firstinf= True;
+
+ FOREACHneighbor_(vertex) {
+ if (neighbor->seen) {
+ if (neighbor->visitid) {
+ if (!neighbor->tricoplanar || qh_setunique (&tricenters, neighbor->center))
+ qh_setappend (&centers, neighbor);
+ }else if (firstinf) {
+ firstinf= False;
+ qh_setappend (&centers, neighbor);
+ }
+ }
+ }
+ qsort (SETaddr_(centers, facetT), qh_setsize (centers),
+ sizeof (facetT *), qh_compare_facetvisit);
+ qh_settempfree (&tricenters);
+ return centers;
+} /* detvridge */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="detvridge3">-</a>
+
+ qh_detvridge3( atvertex, vertex )
+ determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
+ include one vertex-at-infinite for !neighbor->visitid
+ assumes all facet->seen2= True
+
+ returns:
+ temporary set of centers (facets, i.e., Voronoi vertices)
+ listed in adjacency order (not oriented)
+ all facet->seen2= True
+
+ design:
+ mark all neighbors of atvertex
+ for each adjacent neighbor of both atvertex and vertex
+ if neighbor selected
+ add neighbor to set of Voronoi vertices
+*/
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
+ setT *centers= qh_settemp (qh TEMPsize);
+ setT *tricenters= qh_settemp (qh TEMPsize);
+ facetT *neighbor, **neighborp, *facet= NULL;
+ boolT firstinf= True;
+
+ FOREACHneighbor_(atvertex)
+ neighbor->seen2= False;
+ FOREACHneighbor_(vertex) {
+ if (!neighbor->seen2) {
+ facet= neighbor;
+ break;
+ }
+ }
+ while (facet) {
+ facet->seen2= True;
+ if (neighbor->seen) {
+ if (facet->visitid) {
+ if (!facet->tricoplanar || qh_setunique (&tricenters, facet->center))
+ qh_setappend (&centers, facet);
+ }else if (firstinf) {
+ firstinf= False;
+ qh_setappend (&centers, facet);
+ }
+ }
+ FOREACHneighbor_(facet) {
+ if (!neighbor->seen2) {
+ if (qh_setin (vertex->neighbors, neighbor))
+ break;
+ else
+ neighbor->seen2= True;
+ }
+ }
+ facet= neighbor;
+ }
+ if (qh CHECKfrequently) {
+ FOREACHneighbor_(vertex) {
+ if (!neighbor->seen2) {
+ fprintf (stderr, "qh_detvridge3: neigbors of vertex p%d are not connected at facet %d\n",
+ qh_pointid (vertex->point), neighbor->id);
+ qh_errexit (qh_ERRqhull, neighbor, NULL);
+ }
+ }
+ }
+ FOREACHneighbor_(atvertex)
+ neighbor->seen2= True;
+ qh_settempfree (&tricenters);
+ return centers;
+} /* detvridge3 */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="eachvoronoi">-</a>
+
+ qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
+ if visitall,
+ visit all Voronoi ridges for vertex (i.e., an input site)
+ else
+ visit all unvisited Voronoi ridges for vertex
+ all vertex->seen= False if unvisited
+ assumes
+ all facet->seen= False
+ all facet->seen2= True (for qh_detvridge3)
+ all facet->visitid == 0 if vertex_at_infinity
+ == index of Voronoi vertex
+ >= qh.num_facets if ignored
+ innerouter:
+ qh_RIDGEall-- both inner (bounded) and outer (unbounded) ridges
+ qh_RIDGEinner- only inner
+ qh_RIDGEouter- only outer
+
+ if inorder
+ orders vertices for 3-d Voronoi diagrams
+
+ returns:
+ number of visited ridges (does not include previously visited ridges)
+
+ if printvridge,
+ calls printvridge( fp, vertex, vertexA, centers)
+ fp== any pointer (assumes FILE*)
+ vertex,vertexA= pair of input sites that define a Voronoi ridge
+ centers= set of facets (i.e., Voronoi vertices)
+ ->visitid == index or 0 if vertex_at_infinity
+ ordered for 3-d Voronoi diagram
+ notes:
+ uses qh.vertex_visit
+
+ see:
+ qh_eachvoronoi_all()
+
+ design:
+ mark selected neighbors of atvertex
+ for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
+ for each unvisited vertex
+ if atvertex and vertex share more than d-1 neighbors
+ bump totalcount
+ if printvridge defined
+ build the set of shared neighbors (i.e., Voronoi vertices)
+ call printvridge
+*/
+int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
+ boolT unbounded;
+ int count;
+ facetT *neighbor, **neighborp, *neighborA, **neighborAp;
+ setT *centers;
+ setT *tricenters= qh_settemp (qh TEMPsize);
+
+ vertexT *vertex, **vertexp;
+ boolT firstinf;
+ unsigned int numfacets= (unsigned int)qh num_facets;
+ int totridges= 0;
+
+ qh vertex_visit++;
+ atvertex->seen= True;
+ if (visitall) {
+ FORALLvertices
+ vertex->seen= False;
+ }
+ FOREACHneighbor_(atvertex) {
+ if (neighbor->visitid < numfacets)
+ neighbor->seen= True;
+ }
+ FOREACHneighbor_(atvertex) {
+ if (neighbor->seen) {
+ FOREACHvertex_(neighbor->vertices) {
+ if (vertex->visitid != qh vertex_visit && !vertex->seen) {
+ vertex->visitid= qh vertex_visit;
+ count= 0;
+ firstinf= True;
+ qh_settruncate (tricenters, 0);
+ FOREACHneighborA_(vertex) {
+ if (neighborA->seen) {
+ if (neighborA->visitid) {
+ if (!neighborA->tricoplanar || qh_setunique (&tricenters, neighborA->center))
+ count++;
+ }else if (firstinf) {
+ count++;
+ firstinf= False;
+ }
+ }
+ }
+ if (count >= qh hull_dim - 1) { /* e.g., 3 for 3-d Voronoi */
+ if (firstinf) {
+ if (innerouter == qh_RIDGEouter)
+ continue;
+ unbounded= False;
+ }else {
+ if (innerouter == qh_RIDGEinner)
+ continue;
+ unbounded= True;
+ }
+ totridges++;
+ trace4((qh ferr, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
+ count, qh_pointid (atvertex->point), qh_pointid (vertex->point)));
+ if (printvridge) {
+ if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
+ centers= qh_detvridge3 (atvertex, vertex);
+ else
+ centers= qh_detvridge (vertex);
+ (*printvridge) (fp, atvertex, vertex, centers, unbounded);
+ qh_settempfree (&centers);
+ }
+ }
+ }
+ }
+ }
+ }
+ FOREACHneighbor_(atvertex)
+ neighbor->seen= False;
+ qh_settempfree (&tricenters);
+ return totridges;
+} /* eachvoronoi */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="eachvoronoi_all">-</a>
+
+ qh_eachvoronoi_all( fp, printvridge, isupper, innerouter, inorder )
+ visit all Voronoi ridges
+
+ innerouter:
+ see qh_eachvoronoi()
+
+ if inorder
+ orders vertices for 3-d Voronoi diagrams
+
+ returns
+ total number of ridges
+
+ if isupper == facet->upperdelaunay (i.e., a Vornoi vertex)
+ facet->visitid= Voronoi vertex index (same as 'o' format)
+ else
+ facet->visitid= 0
+
+ if printvridge,
+ calls printvridge( fp, vertex, vertexA, centers)
+ [see qh_eachvoronoi]
+
+ notes:
+ Not used for qhull.exe
+ same effect as qh_printvdiagram but ridges not sorted by point id
+*/
+int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder) {
+ facetT *facet;
+ vertexT *vertex;
+ int numcenters= 1; /* vertex 0 is vertex-at-infinity */
+ int totridges= 0;
+
+ qh_clearcenters (qh_ASvoronoi);
+ qh_vertexneighbors();
+ maximize_(qh visit_id, (unsigned) qh num_facets);
+ FORALLfacets {
+ facet->visitid= 0;
+ facet->seen= False;
+ facet->seen2= True;
+ }
+ FORALLfacets {
+ if (facet->upperdelaunay == isupper)
+ facet->visitid= numcenters++;
+ }
+ FORALLvertices
+ vertex->seen= False;
+ FORALLvertices {
+ if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+ continue;
+ totridges += qh_eachvoronoi (fp, printvridge, vertex,
+ !qh_ALL, innerouter, inorder);
+ }
+ return totridges;
+} /* eachvoronoi_all */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="facet2point">-</a>
+
+ qh_facet2point( facet, point0, point1, mindist )
+ return two projected temporary vertices for a 2-d facet
+ may be non-simplicial
+
+ returns:
+ point0 and point1 oriented and projected to the facet
+ returns mindist (maximum distance below plane)
+*/
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
+ vertexT *vertex0, *vertex1;
+ realT dist;
+
+ if (facet->toporient ^ qh_ORIENTclock) {
+ vertex0= SETfirstt_(facet->vertices, vertexT);
+ vertex1= SETsecondt_(facet->vertices, vertexT);
+ }else {
+ vertex1= SETfirstt_(facet->vertices, vertexT);
+ vertex0= SETsecondt_(facet->vertices, vertexT);
+ }
+ zadd_(Zdistio, 2);
+ qh_distplane(vertex0->point, facet, &dist);
+ *mindist= dist;
+ *point0= qh_projectpoint(vertex0->point, facet, dist);
+ qh_distplane(vertex1->point, facet, &dist);
+ minimize_(*mindist, dist);
+ *point1= qh_projectpoint(vertex1->point, facet, dist);
+} /* facet2point */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="facetvertices">-</a>
+
+ qh_facetvertices( facetlist, facets, allfacets )
+ returns temporary set of vertices in a set and/or list of facets
+ if allfacets, ignores qh_skipfacet()
+
+ returns:
+ vertices with qh.vertex_visit
+
+ notes:
+ optimized for allfacets of facet_list
+
+ design:
+ if allfacets of facet_list
+ create vertex set from vertex_list
+ else
+ for each selected facet in facets or facetlist
+ append unvisited vertices to vertex set
+*/
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets) {
+ setT *vertices;
+ facetT *facet, **facetp;
+ vertexT *vertex, **vertexp;
+
+ qh vertex_visit++;
+ if (facetlist == qh facet_list && allfacets && !facets) {
+ vertices= qh_settemp (qh num_vertices);
+ FORALLvertices {
+ vertex->visitid= qh vertex_visit;
+ qh_setappend (&vertices, vertex);
+ }
+ }else {
+ vertices= qh_settemp (qh TEMPsize);
+ FORALLfacet_(facetlist) {
+ if (!allfacets && qh_skipfacet (facet))
+ continue;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ vertex->visitid= qh vertex_visit;
+ qh_setappend (&vertices, vertex);
+ }
+ }
+ }
+ }
+ FOREACHfacet_(facets) {
+ if (!allfacets && qh_skipfacet (facet))
+ continue;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ vertex->visitid= qh vertex_visit;
+ qh_setappend (&vertices, vertex);
+ }
+ }
+ }
+ return vertices;
+} /* facetvertices */
+
+/*-<a href="qh-geom.htm#TOC"
+ >-------------------------------</a><a name="geomplanes">-</a>
+
+ qh_geomplanes( facet, outerplane, innerplane )
+ return outer and inner planes for Geomview
+ qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
+
+ notes:
+ assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+*/
+void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane) {
+ realT radius;
+
+ if (qh MERGING || qh JOGGLEmax < REALmax/2) {
+ qh_outerinner (facet, outerplane, innerplane);
+ radius= qh PRINTradius;
+ if (qh JOGGLEmax < REALmax/2)
+ radius -= qh JOGGLEmax * sqrt (qh hull_dim); /* already accounted for in qh_outerinner() */
+ *outerplane += radius;
+ *innerplane -= radius;
+ if (qh PRINTcoplanar || qh PRINTspheres) {
+ *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
+ *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
+ }
+ }else
+ *innerplane= *outerplane= 0;
+} /* geomplanes */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="markkeep">-</a>
+
+ qh_markkeep( facetlist )
+ mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
+ ignores visible facets (not part of convex hull)
+
+ returns:
+ may clear facet->good
+ recomputes qh.num_good
+
+ design:
+ get set of good facets
+ if qh.KEEParea
+ sort facets by area
+ clear facet->good for all but n largest facets
+ if qh.KEEPmerge
+ sort facets by merge count
+ clear facet->good for all but n most merged facets
+ if qh.KEEPminarea
+ clear facet->good if area too small
+ update qh.num_good
+*/
+void qh_markkeep (facetT *facetlist) {
+ facetT *facet, **facetp;
+ setT *facets= qh_settemp (qh num_facets);
+ int size, count;
+
+ trace2((qh ferr, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
+ qh KEEParea, qh KEEPmerge, qh KEEPminArea));
+ FORALLfacet_(facetlist) {
+ if (!facet->visible && facet->good)
+ qh_setappend (&facets, facet);
+ }
+ size= qh_setsize (facets);
+ if (qh KEEParea) {
+ qsort (SETaddr_(facets, facetT), size,
+ sizeof (facetT *), qh_compare_facetarea);
+ if ((count= size - qh KEEParea) > 0) {
+ FOREACHfacet_(facets) {
+ facet->good= False;
+ if (--count == 0)
+ break;
+ }
+ }
+ }
+ if (qh KEEPmerge) {
+ qsort (SETaddr_(facets, facetT), size,
+ sizeof (facetT *), qh_compare_facetmerge);
+ if ((count= size - qh KEEPmerge) > 0) {
+ FOREACHfacet_(facets) {
+ facet->good= False;
+ if (--count == 0)
+ break;
+ }
+ }
+ }
+ if (qh KEEPminArea < REALmax/2) {
+ FOREACHfacet_(facets) {
+ if (!facet->isarea || facet->f.area < qh KEEPminArea)
+ facet->good= False;
+ }
+ }
+ qh_settempfree (&facets);
+ count= 0;
+ FORALLfacet_(facetlist) {
+ if (facet->good)
+ count++;
+ }
+ qh num_good= count;
+} /* markkeep */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="markvoronoi">-</a>
+
+ qh_markvoronoi( facetlist, facets, printall, islower, numcenters )
+ mark voronoi vertices for printing by site pairs
+
+ returns:
+ temporary set of vertices indexed by pointid
+ islower set if printing lower hull (i.e., at least one facet is lower hull)
+ numcenters= total number of Voronoi vertices
+ bumps qh.printoutnum for vertex-at-infinity
+ clears all facet->seen and sets facet->seen2
+
+ if selected
+ facet->visitid= Voronoi vertex id
+ else if upper hull (or 'Qu' and lower hull)
+ facet->visitid= 0
+ else
+ facet->visitid >= qh num_facets
+
+ notes:
+ ignores qh.ATinfinity, if defined
+*/
+setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp) {
+ int numcenters=0;
+ facetT *facet, **facetp;
+ setT *vertices;
+ boolT islower= False;
+
+ qh printoutnum++;
+ qh_clearcenters (qh_ASvoronoi); /* in case, qh_printvdiagram2 called by user */
+ qh_vertexneighbors();
+ vertices= qh_pointvertex();
+ if (qh ATinfinity)
+ SETelem_(vertices, qh num_points-1)= NULL;
+ qh visit_id++;
+ maximize_(qh visit_id, (unsigned) qh num_facets);
+ FORALLfacet_(facetlist) {
+ if (printall || !qh_skipfacet (facet)) {
+ if (!facet->upperdelaunay) {
+ islower= True;
+ break;
+ }
+ }
+ }
+ FOREACHfacet_(facets) {
+ if (printall || !qh_skipfacet (facet)) {
+ if (!facet->upperdelaunay) {
+ islower= True;
+ break;
+ }
+ }
+ }
+ FORALLfacets {
+ if (facet->normal && (facet->upperdelaunay == islower))
+ facet->visitid= 0; /* facetlist or facets may overwrite */
+ else
+ facet->visitid= qh visit_id;
+ facet->seen= False;
+ facet->seen2= True;
+ }
+ numcenters++; /* qh_INFINITE */
+ FORALLfacet_(facetlist) {
+ if (printall || !qh_skipfacet (facet))
+ facet->visitid= numcenters++;
+ }
+ FOREACHfacet_(facets) {
+ if (printall || !qh_skipfacet (facet))
+ facet->visitid= numcenters++;
+ }
+ *islowerp= islower;
+ *numcentersp= numcenters;
+ trace2((qh ferr, "qh_markvoronoi: islower %d numcenters %d\n", islower, numcenters));
+ return vertices;
+} /* markvoronoi */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="order_vertexneighbors">-</a>
+
+ qh_order_vertexneighbors( vertex )
+ order facet neighbors of a 2-d or 3-d vertex by adjacency
+
+ notes:
+ does not orient the neighbors
+
+ design:
+ initialize a new neighbor set with the first facet in vertex->neighbors
+ while vertex->neighbors non-empty
+ select next neighbor in the previous facet's neighbor set
+ set vertex->neighbors to the new neighbor set
+*/
+void qh_order_vertexneighbors(vertexT *vertex) {
+ setT *newset;
+ facetT *facet, *neighbor, **neighborp;
+
+ trace4((qh ferr, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
+ newset= qh_settemp (qh_setsize (vertex->neighbors));
+ facet= (facetT*)qh_setdellast (vertex->neighbors);
+ qh_setappend (&newset, facet);
+ while (qh_setsize (vertex->neighbors)) {
+ FOREACHneighbor_(vertex) {
+ if (qh_setin (facet->neighbors, neighbor)) {
+ qh_setdel(vertex->neighbors, neighbor);
+ qh_setappend (&newset, neighbor);
+ facet= neighbor;
+ break;
+ }
+ }
+ if (!neighbor) {
+ fprintf (qh ferr, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
+ vertex->id, facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ }
+ qh_setfree (&vertex->neighbors);
+ qh_settemppop ();
+ vertex->neighbors= newset;
+} /* order_vertexneighbors */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printafacet">-</a>
+
+ qh_printafacet( fp, format, facet, printall )
+ print facet to fp in given output format (see qh.PRINTout)
+
+ returns:
+ nop if !printall and qh_skipfacet()
+ nop if visible facet and NEWfacets and format != PRINTfacets
+ must match qh_countfacets
+
+ notes
+ preserves qh.visit_id
+ facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
+
+ see
+ qh_printbegin() and qh_printend()
+
+ design:
+ test for printing facet
+ call appropriate routine for format
+ or output results directly
+*/
+void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall) {
+ realT color[4], offset, dist, outerplane, innerplane;
+ boolT zerodiv;
+ coordT *point, *normp, *coordp, **pointp, *feasiblep;
+ int k;
+ vertexT *vertex, **vertexp;
+ facetT *neighbor, **neighborp;
+
+ if (!printall && qh_skipfacet (facet))
+ return;
+ if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
+ return;
+ qh printoutnum++;
+ switch (format) {
+ case qh_PRINTarea:
+ if (facet->isarea) {
+ fprintf (fp, qh_REAL_1, facet->f.area);
+ fprintf (fp, "\n");
+ }else
+ fprintf (fp, "0\n");
+ break;
+ case qh_PRINTcoplanars:
+ fprintf (fp, "%d", qh_setsize (facet->coplanarset));
+ FOREACHpoint_(facet->coplanarset)
+ fprintf (fp, " %d", qh_pointid (point));
+ fprintf (fp, "\n");
+ break;
+ case qh_PRINTcentrums:
+ qh_printcenter (fp, format, NULL, facet);
+ break;
+ case qh_PRINTfacets:
+ qh_printfacet (fp, facet);
+ break;
+ case qh_PRINTfacets_xridge:
+ qh_printfacetheader (fp, facet);
+ break;
+ case qh_PRINTgeom: /* either 2 , 3, or 4-d by qh_printbegin */
+ if (!facet->normal)
+ break;
+ for (k= qh hull_dim; k--; ) {
+ color[k]= (facet->normal[k]+1.0)/2.0;
+ maximize_(color[k], -1.0);
+ minimize_(color[k], +1.0);
+ }
+ qh_projectdim3 (color, color);
+ if (qh PRINTdim != qh hull_dim)
+ qh_normalize2 (color, 3, True, NULL, NULL);
+ if (qh hull_dim <= 2)
+ qh_printfacet2geom (fp, facet, color);
+ else if (qh hull_dim == 3) {
+ if (facet->simplicial)
+ qh_printfacet3geom_simplicial (fp, facet, color);
+ else
+ qh_printfacet3geom_nonsimplicial (fp, facet, color);
+ }else {
+ if (facet->simplicial)
+ qh_printfacet4geom_simplicial (fp, facet, color);
+ else
+ qh_printfacet4geom_nonsimplicial (fp, facet, color);
+ }
+ break;
+ case qh_PRINTids:
+ fprintf (fp, "%d\n", facet->id);
+ break;
+ case qh_PRINTincidences:
+ case qh_PRINToff:
+ case qh_PRINTtriangles:
+ if (qh hull_dim == 3 && format != qh_PRINTtriangles)
+ qh_printfacet3vertex (fp, facet, format);
+ else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
+ qh_printfacetNvertex_simplicial (fp, facet, format);
+ else
+ qh_printfacetNvertex_nonsimplicial (fp, facet, qh printoutvar++, format);
+ break;
+ case qh_PRINTinner:
+ qh_outerinner (facet, NULL, &innerplane);
+ offset= facet->offset - innerplane;
+ goto LABELprintnorm;
+ break; /* prevent warning */
+ case qh_PRINTmerges:
+ fprintf (fp, "%d\n", facet->nummerge);
+ break;
+ case qh_PRINTnormals:
+ offset= facet->offset;
+ goto LABELprintnorm;
+ break; /* prevent warning */
+ case qh_PRINTouter:
+ qh_outerinner (facet, &outerplane, NULL);
+ offset= facet->offset - outerplane;
+ LABELprintnorm:
+ if (!facet->normal) {
+ fprintf (fp, "no normal for facet f%d\n", facet->id);
+ break;
+ }
+ if (qh CDDoutput) {
+ fprintf (fp, qh_REAL_1, -offset);
+ for (k=0; k < qh hull_dim; k++)
+ fprintf (fp, qh_REAL_1, -facet->normal[k]);
+ }else {
+ for (k=0; k < qh hull_dim; k++)
+ fprintf (fp, qh_REAL_1, facet->normal[k]);
+ fprintf (fp, qh_REAL_1, offset);
+ }
+ fprintf (fp, "\n");
+ break;
+ case qh_PRINTmathematica: /* either 2 or 3-d by qh_printbegin */
+ if (qh hull_dim == 2)
+ qh_printfacet2math (fp, facet, qh printoutvar++);
+ else
+ qh_printfacet3math (fp, facet, qh printoutvar++);
+ break;
+ case qh_PRINTneighbors:
+ fprintf (fp, "%d", qh_setsize (facet->neighbors));
+ FOREACHneighbor_(facet)
+ fprintf (fp, " %d",
+ neighbor->visitid ? neighbor->visitid - 1: - neighbor->id);
+ fprintf (fp, "\n");
+ break;
+ case qh_PRINTpointintersect:
+ if (!qh feasible_point) {
+ fprintf (fp, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
+ qh_errexit( qh_ERRinput, NULL, NULL);
+ }
+ if (facet->offset > 0)
+ goto LABELprintinfinite;
+ point= coordp= (coordT*)qh_memalloc (qh normal_size);
+ normp= facet->normal;
+ feasiblep= qh feasible_point;
+ if (facet->offset < -qh MINdenom) {
+ for (k= qh hull_dim; k--; )
+ *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
+ }else {
+ for (k= qh hull_dim; k--; ) {
+ *(coordp++)= qh_divzero (*(normp++), facet->offset, qh MINdenom_1,
+ &zerodiv) + *(feasiblep++);
+ if (zerodiv) {
+ qh_memfree (point, qh normal_size);
+ goto LABELprintinfinite;
+ }
+ }
+ }
+ qh_printpoint (fp, NULL, point);
+ qh_memfree (point, qh normal_size);
+ break;
+ LABELprintinfinite:
+ for (k= qh hull_dim; k--; )
+ fprintf (fp, qh_REAL_1, qh_INFINITE);
+ fprintf (fp, "\n");
+ break;
+ case qh_PRINTpointnearest:
+ FOREACHpoint_(facet->coplanarset) {
+ int id, id2;
+ vertex= qh_nearvertex (facet, point, &dist);
+ id= qh_pointid (vertex->point);
+ id2= qh_pointid (point);
+ fprintf (fp, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
+ }
+ break;
+ case qh_PRINTpoints: /* VORONOI only by qh_printbegin */
+ if (qh CDDoutput)
+ fprintf (fp, "1 ");
+ qh_printcenter (fp, format, NULL, facet);
+ break;
+ case qh_PRINTvertices:
+ fprintf (fp, "%d", qh_setsize (facet->vertices));
+ FOREACHvertex_(facet->vertices)
+ fprintf (fp, " %d", qh_pointid (vertex->point));
+ fprintf (fp, "\n");
+ break;
+ }
+} /* printafacet */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printbegin">-</a>
+
+ qh_printbegin( )
+ prints header for all output formats
+
+ returns:
+ checks for valid format
+
+ notes:
+ uses qh.visit_id for 3/4off
+ changes qh.interior_point if printing centrums
+ qh_countfacets clears facet->visitid for non-good facets
+
+ see
+ qh_printend() and qh_printafacet()
+
+ design:
+ count facets and related statistics
+ print header for format
+*/
+void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+ int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+ int i, num;
+ facetT *facet, **facetp;
+ vertexT *vertex, **vertexp;
+ setT *vertices;
+ pointT *point, **pointp, *pointtemp;
+
+ qh printoutnum= 0;
+ qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial,
+ &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+ switch (format) {
+ case qh_PRINTnone:
+ break;
+ case qh_PRINTarea:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINTcoplanars:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINTcentrums:
+ if (qh CENTERtype == qh_ASnone)
+ qh_clearcenters (qh_AScentrum);
+ fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
+ break;
+ case qh_PRINTfacets:
+ case qh_PRINTfacets_xridge:
+ if (facetlist)
+ qh_printvertexlist (fp, "Vertices and facets:\n", facetlist, facets, printall);
+ break;
+ case qh_PRINTgeom:
+ if (qh hull_dim > 4) /* qh_initqhull_globals also checks */
+ goto LABELnoformat;
+ if (qh VORONOI && qh hull_dim > 3) /* PRINTdim == DROPdim == hull_dim-1 */
+ goto LABELnoformat;
+ if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
+ fprintf (qh ferr, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
+ if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
+ (qh PRINTdim == 4 && qh PRINTcentrums)))
+ fprintf (qh ferr, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
+ if (qh PRINTdim == 4 && (qh PRINTspheres))
+ fprintf (qh ferr, "qhull warning: output for vertices not implemented in 4-d\n");
+ if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
+ fprintf (qh ferr, "qhull warning: 'Gnh' generates no output in 4-d\n");
+ if (qh PRINTdim == 2) {
+ fprintf(fp, "{appearance {linewidth 3} LIST # %s | %s\n",
+ qh rbox_command, qh qhull_command);
+ }else if (qh PRINTdim == 3) {
+ fprintf(fp, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
+ qh rbox_command, qh qhull_command);
+ }else if (qh PRINTdim == 4) {
+ qh visit_id++;
+ num= 0;
+ FORALLfacet_(facetlist) /* get number of ridges to be printed */
+ qh_printend4geom (NULL, facet, &num, printall);
+ FOREACHfacet_(facets)
+ qh_printend4geom (NULL, facet, &num, printall);
+ qh ridgeoutnum= num;
+ qh printoutvar= 0; /* counts number of ridges in output */
+ fprintf (fp, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
+ }
+ if (qh PRINTdots) {
+ qh printoutnum++;
+ num= qh num_points + qh_setsize (qh other_points);
+ if (qh DELAUNAY && qh ATinfinity)
+ num--;
+ if (qh PRINTdim == 4)
+ fprintf (fp, "4VECT %d %d 1\n", num, num);
+ else
+ fprintf (fp, "VECT %d %d 1\n", num, num);
+ for (i= num; i--; ) {
+ if (i % 20 == 0)
+ fprintf (fp, "\n");
+ fprintf (fp, "1 ");
+ }
+ fprintf (fp, "# 1 point per line\n1 ");
+ for (i= num-1; i--; ) {
+ if (i % 20 == 0)
+ fprintf (fp, "\n");
+ fprintf (fp, "0 ");
+ }
+ fprintf (fp, "# 1 color for all\n");
+ FORALLpoints {
+ if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
+ if (qh PRINTdim == 4)
+ qh_printpoint (fp, NULL, point);
+ else
+ qh_printpoint3 (fp, point);
+ }
+ }
+ FOREACHpoint_(qh other_points) {
+ if (qh PRINTdim == 4)
+ qh_printpoint (fp, NULL, point);
+ else
+ qh_printpoint3 (fp, point);
+ }
+ fprintf (fp, "0 1 1 1 # color of points\n");
+ }
+ if (qh PRINTdim == 4 && !qh PRINTnoplanes)
+ /* 4dview loads up multiple 4OFF objects slowly */
+ fprintf(fp, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
+ qh PRINTcradius= 2 * qh DISTround; /* include test DISTround */
+ if (qh PREmerge) {
+ maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
+ }else if (qh POSTmerge)
+ maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
+ qh PRINTradius= qh PRINTcradius;
+ if (qh PRINTspheres + qh PRINTcoplanar)
+ maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
+ if (qh premerge_cos < REALmax/2) {
+ maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
+ }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
+ maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
+ }
+ maximize_(qh PRINTradius, qh MINvisible);
+ if (qh JOGGLEmax < REALmax/2)
+ qh PRINTradius += qh JOGGLEmax * sqrt (qh hull_dim);
+ if (qh PRINTdim != 4 &&
+ (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ if (qh PRINTspheres && qh PRINTdim <= 3)
+ qh_printspheres (fp, vertices, qh PRINTradius);
+ if (qh PRINTcoplanar || qh PRINTcentrums) {
+ qh firstcentrum= True;
+ if (qh PRINTcoplanar&& !qh PRINTspheres) {
+ FOREACHvertex_(vertices)
+ qh_printpointvect2 (fp, vertex->point, NULL,
+ qh interior_point, qh PRINTradius);
+ }
+ FORALLfacet_(facetlist) {
+ if (!printall && qh_skipfacet(facet))
+ continue;
+ if (!facet->normal)
+ continue;
+ if (qh PRINTcentrums && qh PRINTdim <= 3)
+ qh_printcentrum (fp, facet, qh PRINTcradius);
+ if (!qh PRINTcoplanar)
+ continue;
+ FOREACHpoint_(facet->coplanarset)
+ qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+ FOREACHpoint_(facet->outsideset)
+ qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+ }
+ FOREACHfacet_(facets) {
+ if (!printall && qh_skipfacet(facet))
+ continue;
+ if (!facet->normal)
+ continue;
+ if (qh PRINTcentrums && qh PRINTdim <= 3)
+ qh_printcentrum (fp, facet, qh PRINTcradius);
+ if (!qh PRINTcoplanar)
+ continue;
+ FOREACHpoint_(facet->coplanarset)
+ qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+ FOREACHpoint_(facet->outsideset)
+ qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+ }
+ }
+ qh_settempfree (&vertices);
+ }
+ qh visit_id++; /* for printing hyperplane intersections */
+ break;
+ case qh_PRINTids:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINTincidences:
+ if (qh VORONOI && qh PRINTprecision)
+ fprintf (qh ferr, "qhull warning: writing Delaunay. Use 'p' or 'o' for Voronoi centers\n");
+ qh printoutvar= qh vertex_id; /* centrum id for non-simplicial facets */
+ if (qh hull_dim <= 3)
+ fprintf(fp, "%d\n", numfacets);
+ else
+ fprintf(fp, "%d\n", numsimplicial+numridges);
+ break;
+ case qh_PRINTinner:
+ case qh_PRINTnormals:
+ case qh_PRINTouter:
+ if (qh CDDoutput)
+ fprintf (fp, "%s | %s\nbegin\n %d %d real\n", qh rbox_command,
+ qh qhull_command, numfacets, qh hull_dim+1);
+ else
+ fprintf (fp, "%d\n%d\n", qh hull_dim+1, numfacets);
+ break;
+ case qh_PRINTmathematica:
+ if (qh hull_dim > 3) /* qh_initbuffers also checks */
+ goto LABELnoformat;
+ if (qh VORONOI)
+ fprintf (qh ferr, "qhull warning: output is the Delaunay triangulation\n");
+ fprintf(fp, "{\n");
+ qh printoutvar= 0; /* counts number of facets for notfirst */
+ break;
+ case qh_PRINTmerges:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINTpointintersect:
+ fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
+ break;
+ case qh_PRINTneighbors:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINToff:
+ case qh_PRINTtriangles:
+ if (qh VORONOI)
+ goto LABELnoformat;
+ num = qh hull_dim;
+ if (format == qh_PRINToff || qh hull_dim == 2)
+ fprintf (fp, "%d\n%d %d %d\n", num,
+ qh num_points+qh_setsize (qh other_points), numfacets, totneighbors/2);
+ else { /* qh_PRINTtriangles */
+ qh printoutvar= qh num_points+qh_setsize (qh other_points); /* first centrum */
+ if (qh DELAUNAY)
+ num--; /* drop last dimension */
+ fprintf (fp, "%d\n%d %d %d\n", num, qh printoutvar
+ + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
+ }
+ FORALLpoints
+ qh_printpointid (qh fout, NULL, num, point, -1);
+ FOREACHpoint_(qh other_points)
+ qh_printpointid (qh fout, NULL, num, point, -1);
+ if (format == qh_PRINTtriangles && qh hull_dim > 2) {
+ FORALLfacets {
+ if (!facet->simplicial && facet->visitid)
+ qh_printcenter (qh fout, format, NULL, facet);
+ }
+ }
+ break;
+ case qh_PRINTpointnearest:
+ fprintf (fp, "%d\n", numcoplanars);
+ break;
+ case qh_PRINTpoints:
+ if (!qh VORONOI)
+ goto LABELnoformat;
+ if (qh CDDoutput)
+ fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+ qh qhull_command, numfacets, qh hull_dim);
+ else
+ fprintf (fp, "%d\n%d\n", qh hull_dim-1, numfacets);
+ break;
+ case qh_PRINTvertices:
+ fprintf (fp, "%d\n", numfacets);
+ break;
+ case qh_PRINTsummary:
+ default:
+ LABELnoformat:
+ fprintf (qh ferr, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
+ qh hull_dim);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+} /* printbegin */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printcenter">-</a>
+
+ qh_printcenter( fp, string, facet )
+ print facet->center as centrum or Voronoi center
+ string may be NULL. Don't include '%' codes.
+ nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
+ if upper envelope of Delaunay triangulation and point at-infinity
+ prints qh_INFINITE instead;
+
+ notes:
+ defines facet->center if needed
+ if format=PRINTgeom, adds a 0 if would otherwise be 2-d
+*/
+void qh_printcenter (FILE *fp, int format, char *string, facetT *facet) {
+ int k, num;
+
+ if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
+ return;
+ if (string)
+ fprintf (fp, string, facet->id);
+ if (qh CENTERtype == qh_ASvoronoi) {
+ num= qh hull_dim-1;
+ if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
+ if (!facet->center)
+ facet->center= qh_facetcenter (facet->vertices);
+ for (k=0; k < num; k++)
+ fprintf (fp, qh_REAL_1, facet->center[k]);
+ }else {
+ for (k=0; k < num; k++)
+ fprintf (fp, qh_REAL_1, qh_INFINITE);
+ }
+ }else /* qh CENTERtype == qh_AScentrum */ {
+ num= qh hull_dim;
+ if (format == qh_PRINTtriangles && qh DELAUNAY)
+ num--;
+ if (!facet->center)
+ facet->center= qh_getcentrum (facet);
+ for (k=0; k < num; k++)
+ fprintf (fp, qh_REAL_1, facet->center[k]);
+ }
+ if (format == qh_PRINTgeom && num == 2)
+ fprintf (fp, " 0\n");
+ else
+ fprintf (fp, "\n");
+} /* printcenter */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printcentrum">-</a>
+
+ qh_printcentrum( fp, facet, radius )
+ print centrum for a facet in OOGL format
+ radius defines size of centrum
+ 2-d or 3-d only
+
+ returns:
+ defines facet->center if needed
+*/
+void qh_printcentrum (FILE *fp, facetT *facet, realT radius) {
+ pointT *centrum, *projpt;
+ boolT tempcentrum= False;
+ realT xaxis[4], yaxis[4], normal[4], dist;
+ realT green[3]={0, 1, 0};
+ vertexT *apex;
+ int k;
+
+ if (qh CENTERtype == qh_AScentrum) {
+ if (!facet->center)
+ facet->center= qh_getcentrum (facet);
+ centrum= facet->center;
+ }else {
+ centrum= qh_getcentrum (facet);
+ tempcentrum= True;
+ }
+ fprintf (fp, "{appearance {-normal -edge normscale 0} ");
+ if (qh firstcentrum) {
+ qh firstcentrum= False;
+ fprintf (fp, "{INST geom { define centrum CQUAD # f%d\n\
+-0.3 -0.3 0.0001 0 0 1 1\n\
+ 0.3 -0.3 0.0001 0 0 1 1\n\
+ 0.3 0.3 0.0001 0 0 1 1\n\
+-0.3 0.3 0.0001 0 0 1 1 } transform { \n", facet->id);
+ }else
+ fprintf (fp, "{INST geom { : centrum } transform { # f%d\n", facet->id);
+ apex= SETfirstt_(facet->vertices, vertexT);
+ qh_distplane(apex->point, facet, &dist);
+ projpt= qh_projectpoint(apex->point, facet, dist);
+ for (k= qh hull_dim; k--; ) {
+ xaxis[k]= projpt[k] - centrum[k];
+ normal[k]= facet->normal[k];
+ }
+ if (qh hull_dim == 2) {
+ xaxis[2]= 0;
+ normal[2]= 0;
+ }else if (qh hull_dim == 4) {
+ qh_projectdim3 (xaxis, xaxis);
+ qh_projectdim3 (normal, normal);
+ qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
+ }
+ qh_crossproduct (3, xaxis, normal, yaxis);
+ fprintf (fp, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
+ fprintf (fp, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
+ fprintf (fp, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
+ qh_printpoint3 (fp, centrum);
+ fprintf (fp, "1 }}}\n");
+ qh_memfree (projpt, qh normal_size);
+ qh_printpointvect (fp, centrum, facet->normal, NULL, radius, green);
+ if (tempcentrum)
+ qh_memfree (centrum, qh normal_size);
+} /* printcentrum */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printend">-</a>
+
+ qh_printend( fp, format )
+ prints trailer for all output formats
+
+ see:
+ qh_printbegin() and qh_printafacet()
+
+*/
+void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+ int num;
+ facetT *facet, **facetp;
+
+ if (!qh printoutnum)
+ fprintf (qh ferr, "qhull warning: no facets printed\n");
+ switch (format) {
+ case qh_PRINTgeom:
+ if (qh hull_dim == 4 && qh DROPdim < 0 && !qh PRINTnoplanes) {
+ qh visit_id++;
+ num= 0;
+ FORALLfacet_(facetlist)
+ qh_printend4geom (fp, facet,&num, printall);
+ FOREACHfacet_(facets)
+ qh_printend4geom (fp, facet, &num, printall);
+ if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
+ fprintf (qh ferr, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ }else
+ fprintf(fp, "}\n");
+ break;
+ case qh_PRINTinner:
+ case qh_PRINTnormals:
+ case qh_PRINTouter:
+ if (qh CDDoutput)
+ fprintf (fp, "end\n");
+ break;
+ case qh_PRINTmathematica:
+ fprintf(fp, "}\n");
+ break;
+ case qh_PRINTpoints:
+ if (qh CDDoutput)
+ fprintf (fp, "end\n");
+ break;
+ }
+} /* printend */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printend4geom">-</a>
+
+ qh_printend4geom( fp, facet, numridges, printall )
+ helper function for qh_printbegin/printend
+
+ returns:
+ number of printed ridges
+
+ notes:
+ just counts printed ridges if fp=NULL
+ uses facet->visitid
+ must agree with qh_printfacet4geom...
+
+ design:
+ computes color for facet from its normal
+ prints each ridge of facet
+*/
+void qh_printend4geom (FILE *fp, facetT *facet, int *nump, boolT printall) {
+ realT color[3];
+ int i, num= *nump;
+ facetT *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+
+ if (!printall && qh_skipfacet(facet))
+ return;
+ if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+ return;
+ if (!facet->normal)
+ return;
+ if (fp) {
+ for (i=0; i < 3; i++) {
+ color[i]= (facet->normal[i]+1.0)/2.0;
+ maximize_(color[i], -1.0);
+ minimize_(color[i], +1.0);
+ }
+ }
+ facet->visitid= qh visit_id;
+ if (facet->simplicial) {
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid != qh visit_id) {
+ if (fp)
+ fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
+ 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+ facet->id, neighbor->id);
+ num++;
+ }
+ }
+ }else {
+ FOREACHridge_(facet->ridges) {
+ neighbor= otherfacet_(ridge, facet);
+ if (neighbor->visitid != qh visit_id) {
+ if (fp)
+ fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
+ 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+ ridge->id, facet->id, neighbor->id);
+ num++;
+ }
+ }
+ }
+ *nump= num;
+} /* printend4geom */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printextremes">-</a>
+
+ qh_printextremes( fp, facetlist, facets, printall )
+ print extreme points for convex hulls or halfspace intersections
+
+ notes:
+ #points, followed by ids, one per line
+
+ sorted by id
+ same order as qh_printpoints_out if no coplanar/interior points
+*/
+void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+ setT *vertices, *points;
+ pointT *point;
+ vertexT *vertex, **vertexp;
+ int id;
+ int numpoints=0, point_i, point_n;
+ int allpoints= qh num_points + qh_setsize (qh other_points);
+
+ points= qh_settemp (allpoints);
+ qh_setzero (points, 0, allpoints);
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ FOREACHvertex_(vertices) {
+ id= qh_pointid (vertex->point);
+ if (id >= 0) {
+ SETelem_(points, id)= vertex->point;
+ numpoints++;
+ }
+ }
+ qh_settempfree (&vertices);
+ fprintf (fp, "%d\n", numpoints);
+ FOREACHpoint_i_(points) {
+ if (point)
+ fprintf (fp, "%d\n", point_i);
+ }
+ qh_settempfree (&points);
+} /* printextremes */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printextremes_2d">-</a>
+
+ qh_printextremes_2d( fp, facetlist, facets, printall )
+ prints point ids for facets in qh_ORIENTclock order
+
+ notes:
+ #points, followed by ids, one per line
+ if facetlist/facets are disjoint than the output includes skips
+ errors if facets form a loop
+ does not print coplanar points
+*/
+void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+ int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
+ setT *vertices;
+ facetT *facet, *startfacet, *nextfacet;
+ vertexT *vertexA, *vertexB;
+
+ qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial,
+ &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ fprintf(fp, "%d\n", qh_setsize (vertices));
+ qh_settempfree (&vertices);
+ if (!numfacets)
+ return;
+ facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
+ qh vertex_visit++;
+ qh visit_id++;
+ do {
+ if (facet->toporient ^ qh_ORIENTclock) {
+ vertexA= SETfirstt_(facet->vertices, vertexT);
+ vertexB= SETsecondt_(facet->vertices, vertexT);
+ nextfacet= SETfirstt_(facet->neighbors, facetT);
+ }else {
+ vertexA= SETsecondt_(facet->vertices, vertexT);
+ vertexB= SETfirstt_(facet->vertices, vertexT);
+ nextfacet= SETsecondt_(facet->neighbors, facetT);
+ }
+ if (facet->visitid == qh visit_id) {
+ fprintf(qh ferr, "qh_printextremes_2d: loop in facet list. facet %d nextfacet %d\n",
+ facet->id, nextfacet->id);
+ qh_errexit2 (qh_ERRqhull, facet, nextfacet);
+ }
+ if (facet->visitid) {
+ if (vertexA->visitid != qh vertex_visit) {
+ vertexA->visitid= qh vertex_visit;
+ fprintf(fp, "%d\n", qh_pointid (vertexA->point));
+ }
+ if (vertexB->visitid != qh vertex_visit) {
+ vertexB->visitid= qh vertex_visit;
+ fprintf(fp, "%d\n", qh_pointid (vertexB->point));
+ }
+ }
+ facet->visitid= qh visit_id;
+ facet= nextfacet;
+ }while (facet && facet != startfacet);
+} /* printextremes_2d */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printextremes_d">-</a>
+
+ qh_printextremes_d( fp, facetlist, facets, printall )
+ print extreme points of input sites for Delaunay triangulations
+
+ notes:
+ #points, followed by ids, one per line
+
+ unordered
+*/
+void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+ setT *vertices;
+ vertexT *vertex, **vertexp;
+ boolT upperseen, lowerseen;
+ facetT *neighbor, **neighborp;
+ int numpoints=0;
+
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ qh_vertexneighbors();
+ FOREACHvertex_(vertices) {
+ upperseen= lowerseen= False;
+ FOREACHneighbor_(vertex) {
+ if (neighbor->upperdelaunay)
+ upperseen= True;
+ else
+ lowerseen= True;
+ }
+ if (upperseen && lowerseen) {
+ vertex->seen= True;
+ numpoints++;
+ }else
+ vertex->seen= False;
+ }
+ fprintf (fp, "%d\n", numpoints);
+ FOREACHvertex_(vertices) {
+ if (vertex->seen)
+ fprintf (fp, "%d\n", qh_pointid (vertex->point));
+ }
+ qh_settempfree (&vertices);
+} /* printextremes_d */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet">-</a>
+
+ qh_printfacet( fp, facet )
+ prints all fields of a facet to fp
+
+ notes:
+ ridges printed in neighbor order
+*/
+void qh_printfacet(FILE *fp, facetT *facet) {
+
+ qh_printfacetheader (fp, facet);
+ if (facet->ridges)
+ qh_printfacetridges (fp, facet);
+} /* printfacet */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet2geom">-</a>
+
+ qh_printfacet2geom( fp, facet, color )
+ print facet as part of a 2-d VECT for Geomview
+
+ notes:
+ assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+ mindist is calculated within io.c. maxoutside is calculated elsewhere
+ so a DISTround error may have occured.
+*/
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
+ pointT *point0, *point1;
+ realT mindist, innerplane, outerplane;
+ int k;
+
+ qh_facet2point (facet, &point0, &point1, &mindist);
+ qh_geomplanes (facet, &outerplane, &innerplane);
+ if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+ qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
+ if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+ outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+ for(k= 3; k--; )
+ color[k]= 1.0 - color[k];
+ qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
+ }
+ qh_memfree (point1, qh normal_size);
+ qh_memfree (point0, qh normal_size);
+} /* printfacet2geom */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet2geom_points">-</a>
+
+ qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
+ prints a 2-d facet as a VECT with 2 points at some offset.
+ The points are on the facet's plane.
+*/
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+ facetT *facet, realT offset, realT color[3]) {
+ pointT *p1= point1, *p2= point2;
+
+ fprintf(fp, "VECT 1 2 1 2 1 # f%d\n", facet->id);
+ if (offset != 0.0) {
+ p1= qh_projectpoint (p1, facet, -offset);
+ p2= qh_projectpoint (p2, facet, -offset);
+ }
+ fprintf(fp, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
+ p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
+ if (offset != 0.0) {
+ qh_memfree (p1, qh normal_size);
+ qh_memfree (p2, qh normal_size);
+ }
+ fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printfacet2geom_points */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet2math">-</a>
+
+ qh_printfacet2math( fp, facet, notfirst )
+ print 2-d Mathematica output for a facet
+ may be non-simplicial
+
+ notes:
+ use %16.8f since Mathematica 2.2 does not handle exponential format
+*/
+void qh_printfacet2math(FILE *fp, facetT *facet, int notfirst) {
+ pointT *point0, *point1;
+ realT mindist;
+
+ qh_facet2point (facet, &point0, &point1, &mindist);
+ if (notfirst)
+ fprintf(fp, ",");
+ fprintf(fp, "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n",
+ point0[0], point0[1], point1[0], point1[1]);
+ qh_memfree (point1, qh normal_size);
+ qh_memfree (point0, qh normal_size);
+} /* printfacet2math */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
+
+ qh_printfacet3geom_nonsimplicial( fp, facet, color )
+ print Geomview OFF for a 3-d nonsimplicial facet.
+ if DOintersections, prints ridges to unvisited neighbors (qh visit_id)
+
+ notes
+ uses facet->visitid for intersections and ridges
+*/
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+ ridgeT *ridge, **ridgep;
+ setT *projectedpoints, *vertices;
+ vertexT *vertex, **vertexp, *vertexA, *vertexB;
+ pointT *projpt, *point, **pointp;
+ facetT *neighbor;
+ realT dist, outerplane, innerplane;
+ int cntvertices, k;
+ realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+
+ qh_geomplanes (facet, &outerplane, &innerplane);
+ vertices= qh_facet3vertex (facet); /* oriented */
+ cntvertices= qh_setsize(vertices);
+ projectedpoints= qh_settemp(cntvertices);
+ FOREACHvertex_(vertices) {
+ zinc_(Zdistio);
+ qh_distplane(vertex->point, facet, &dist);
+ projpt= qh_projectpoint(vertex->point, facet, dist);
+ qh_setappend (&projectedpoints, projpt);
+ }
+ if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+ qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
+ if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+ outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+ for (k=3; k--; )
+ color[k]= 1.0 - color[k];
+ qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
+ }
+ FOREACHpoint_(projectedpoints)
+ qh_memfree (point, qh normal_size);
+ qh_settempfree(&projectedpoints);
+ qh_settempfree(&vertices);
+ if ((qh DOintersections || qh PRINTridges)
+ && (!facet->visible || !qh NEWfacets)) {
+ facet->visitid= qh visit_id;
+ FOREACHridge_(facet->ridges) {
+ neighbor= otherfacet_(ridge, facet);
+ if (neighbor->visitid != qh visit_id) {
+ if (qh DOintersections)
+ qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
+ if (qh PRINTridges) {
+ vertexA= SETfirstt_(ridge->vertices, vertexT);
+ vertexB= SETsecondt_(ridge->vertices, vertexT);
+ qh_printline3geom (fp, vertexA->point, vertexB->point, green);
+ }
+ }
+ }
+ }
+} /* printfacet3geom_nonsimplicial */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet3geom_points">-</a>
+
+ qh_printfacet3geom_points( fp, points, facet, offset )
+ prints a 3-d facet as OFF Geomview object.
+ offset is relative to the facet's hyperplane
+ Facet is determined as a list of points
+*/
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
+ int k, n= qh_setsize(points), i;
+ pointT *point, **pointp;
+ setT *printpoints;
+
+ fprintf(fp, "{ OFF %d 1 1 # f%d\n", n, facet->id);
+ if (offset != 0.0) {
+ printpoints= qh_settemp (n);
+ FOREACHpoint_(points)
+ qh_setappend (&printpoints, qh_projectpoint(point, facet, -offset));
+ }else
+ printpoints= points;
+ FOREACHpoint_(printpoints) {
+ for (k=0; k < qh hull_dim; k++) {
+ if (k == qh DROPdim)
+ fprintf(fp, "0 ");
+ else
+ fprintf(fp, "%8.4g ", point[k]);
+ }
+ if (printpoints != points)
+ qh_memfree (point, qh normal_size);
+ fprintf (fp, "\n");
+ }
+ if (printpoints != points)
+ qh_settempfree (&printpoints);
+ fprintf(fp, "%d ", n);
+ for(i= 0; i < n; i++)
+ fprintf(fp, "%d ", i);
+ fprintf(fp, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
+} /* printfacet3geom_points */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
+
+ qh_printfacet3geom_simplicial( )
+ print Geomview OFF for a 3-d simplicial facet.
+
+ notes:
+ may flip color
+ uses facet->visitid for intersections and ridges
+
+ assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+ innerplane may be off by qh DISTround. Maxoutside is calculated elsewhere
+ so a DISTround error may have occured.
+*/
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+ setT *points, *vertices;
+ vertexT *vertex, **vertexp, *vertexA, *vertexB;
+ facetT *neighbor, **neighborp;
+ realT outerplane, innerplane;
+ realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+ int k;
+
+ qh_geomplanes (facet, &outerplane, &innerplane);
+ vertices= qh_facet3vertex (facet);
+ points= qh_settemp (qh TEMPsize);
+ FOREACHvertex_(vertices)
+ qh_setappend(&points, vertex->point);
+ if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+ qh_printfacet3geom_points(fp, points, facet, outerplane, color);
+ if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+ outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+ for (k= 3; k--; )
+ color[k]= 1.0 - color[k];
+ qh_printfacet3geom_points(fp, points, facet, innerplane, color);
+ }
+ qh_settempfree(&points);
+ qh_settempfree(&vertices);
+ if ((qh DOintersections || qh PRINTridges)
+ && (!facet->visible || !qh NEWfacets)) {
+ facet->visitid= qh visit_id;
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid != qh visit_id) {
+ vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+ SETindex_(facet->neighbors, neighbor), 0);
+ if (qh DOintersections)
+ qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
+ if (qh PRINTridges) {
+ vertexA= SETfirstt_(vertices, vertexT);
+ vertexB= SETsecondt_(vertices, vertexT);
+ qh_printline3geom (fp, vertexA->point, vertexB->point, green);
+ }
+ qh_setfree(&vertices);
+ }
+ }
+ }
+} /* printfacet3geom_simplicial */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet3math">-</a>
+
+ qh_printfacet3math( fp, facet, notfirst )
+ print 3-d Mathematica output for a facet
+
+ notes:
+ may be non-simplicial
+ use %16.8f since Mathematica 2.2 does not handle exponential format
+*/
+void qh_printfacet3math (FILE *fp, facetT *facet, int notfirst) {
+ vertexT *vertex, **vertexp;
+ setT *points, *vertices;
+ pointT *point, **pointp;
+ boolT firstpoint= True;
+ realT dist;
+
+ if (notfirst)
+ fprintf(fp, ",\n");
+ vertices= qh_facet3vertex (facet);
+ points= qh_settemp (qh_setsize (vertices));
+ FOREACHvertex_(vertices) {
+ zinc_(Zdistio);
+ qh_distplane(vertex->point, facet, &dist);
+ point= qh_projectpoint(vertex->point, facet, dist);
+ qh_setappend (&points, point);
+ }
+ fprintf(fp, "Polygon[{");
+ FOREACHpoint_(points) {
+ if (firstpoint)
+ firstpoint= False;
+ else
+ fprintf(fp, ",\n");
+ fprintf(fp, "{%16.8f, %16.8f, %16.8f}", point[0], point[1], point[2]);
+ }
+ FOREACHpoint_(points)
+ qh_memfree (point, qh normal_size);
+ qh_settempfree(&points);
+ qh_settempfree(&vertices);
+ fprintf(fp, "}]");
+} /* printfacet3math */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet3vertex">-</a>
+
+ qh_printfacet3vertex( fp, facet, format )
+ print vertices in a 3-d facet as point ids
+
+ notes:
+ prints number of vertices first if format == qh_PRINToff
+ the facet may be non-simplicial
+*/
+void qh_printfacet3vertex(FILE *fp, facetT *facet, int format) {
+ vertexT *vertex, **vertexp;
+ setT *vertices;
+
+ vertices= qh_facet3vertex (facet);
+ if (format == qh_PRINToff)
+ fprintf (fp, "%d ", qh_setsize (vertices));
+ FOREACHvertex_(vertices)
+ fprintf (fp, "%d ", qh_pointid(vertex->point));
+ fprintf (fp, "\n");
+ qh_settempfree(&vertices);
+} /* printfacet3vertex */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
+
+ qh_printfacet4geom_nonsimplicial( )
+ print Geomview 4OFF file for a 4d nonsimplicial facet
+ prints all ridges to unvisited neighbors (qh.visit_id)
+ if qh.DROPdim
+ prints in OFF format
+
+ notes:
+ must agree with printend4geom()
+*/
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+ facetT *neighbor;
+ ridgeT *ridge, **ridgep;
+ vertexT *vertex, **vertexp;
+ pointT *point;
+ int k;
+ realT dist;
+
+ facet->visitid= qh visit_id;
+ if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+ return;
+ FOREACHridge_(facet->ridges) {
+ neighbor= otherfacet_(ridge, facet);
+ if (neighbor->visitid == qh visit_id)
+ continue;
+ if (qh PRINTtransparent && !neighbor->good)
+ continue;
+ if (qh DOintersections)
+ qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
+ else {
+ if (qh DROPdim >= 0)
+ fprintf(fp, "OFF 3 1 1 # f%d\n", facet->id);
+ else {
+ qh printoutvar++;
+ fprintf (fp, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
+ }
+ FOREACHvertex_(ridge->vertices) {
+ zinc_(Zdistio);
+ qh_distplane(vertex->point,facet, &dist);
+ point=qh_projectpoint(vertex->point,facet, dist);
+ for(k= 0; k < qh hull_dim; k++) {
+ if (k != qh DROPdim)
+ fprintf(fp, "%8.4g ", point[k]);
+ }
+ fprintf (fp, "\n");
+ qh_memfree (point, qh normal_size);
+ }
+ if (qh DROPdim >= 0)
+ fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+ }
+ }
+} /* printfacet4geom_nonsimplicial */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
+
+ qh_printfacet4geom_simplicial( fp, facet, color )
+ print Geomview 4OFF file for a 4d simplicial facet
+ prints triangles for unvisited neighbors (qh.visit_id)
+
+ notes:
+ must agree with printend4geom()
+*/
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+ setT *vertices;
+ facetT *neighbor, **neighborp;
+ vertexT *vertex, **vertexp;
+ int k;
+
+ facet->visitid= qh visit_id;
+ if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+ return;
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid == qh visit_id)
+ continue;
+ if (qh PRINTtransparent && !neighbor->good)
+ continue;
+ vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+ SETindex_(facet->neighbors, neighbor), 0);
+ if (qh DOintersections)
+ qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
+ else {
+ if (qh DROPdim >= 0)
+ fprintf(fp, "OFF 3 1 1 # ridge between f%d f%d\n",
+ facet->id, neighbor->id);
+ else {
+ qh printoutvar++;
+ fprintf (fp, "# ridge between f%d f%d\n", facet->id, neighbor->id);
+ }
+ FOREACHvertex_(vertices) {
+ for(k= 0; k < qh hull_dim; k++) {
+ if (k != qh DROPdim)
+ fprintf(fp, "%8.4g ", vertex->point[k]);
+ }
+ fprintf (fp, "\n");
+ }
+ if (qh DROPdim >= 0)
+ fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+ }
+ qh_setfree(&vertices);
+ }
+} /* printfacet4geom_simplicial */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
+
+ qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
+ print vertices for an N-d non-simplicial facet
+ triangulates each ridge to the id
+*/
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format) {
+ vertexT *vertex, **vertexp;
+ ridgeT *ridge, **ridgep;
+
+ if (facet->visible && qh NEWfacets)
+ return;
+ FOREACHridge_(facet->ridges) {
+ if (format == qh_PRINTtriangles)
+ fprintf(fp, "%d ", qh hull_dim);
+ fprintf(fp, "%d ", id);
+ if ((ridge->top == facet) ^ qh_ORIENTclock) {
+ FOREACHvertex_(ridge->vertices)
+ fprintf(fp, "%d ", qh_pointid(vertex->point));
+ }else {
+ FOREACHvertexreverse12_(ridge->vertices)
+ fprintf(fp, "%d ", qh_pointid(vertex->point));
+ }
+ fprintf(fp, "\n");
+ }
+} /* printfacetNvertex_nonsimplicial */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
+
+ qh_printfacetNvertex_simplicial( fp, facet, format )
+ print vertices for an N-d simplicial facet
+ prints vertices for non-simplicial facets
+ 2-d facets (orientation preserved by qh_mergefacet2d)
+ PRINToff ('o') for 4-d and higher
+*/
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format) {
+ vertexT *vertex, **vertexp;
+
+ if (format == qh_PRINToff || format == qh_PRINTtriangles)
+ fprintf (fp, "%d ", qh_setsize (facet->vertices));
+ if ((facet->toporient ^ qh_ORIENTclock)
+ || (qh hull_dim > 2 && !facet->simplicial)) {
+ FOREACHvertex_(facet->vertices)
+ fprintf(fp, "%d ", qh_pointid(vertex->point));
+ }else {
+ FOREACHvertexreverse12_(facet->vertices)
+ fprintf(fp, "%d ", qh_pointid(vertex->point));
+ }
+ fprintf(fp, "\n");
+} /* printfacetNvertex_simplicial */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacetheader">-</a>
+
+ qh_printfacetheader( fp, facet )
+ prints header fields of a facet to fp
+
+ notes:
+ for 'f' output and debugging
+*/
+void qh_printfacetheader(FILE *fp, facetT *facet) {
+ pointT *point, **pointp, *furthest;
+ facetT *neighbor, **neighborp;
+ realT dist;
+
+ if (facet == qh_MERGEridge) {
+ fprintf (fp, " MERGEridge\n");
+ return;
+ }else if (facet == qh_DUPLICATEridge) {
+ fprintf (fp, " DUPLICATEridge\n");
+ return;
+ }else if (!facet) {
+ fprintf (fp, " NULLfacet\n");
+ return;
+ }
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ fprintf(fp, "- f%d\n", facet->id);
+ fprintf(fp, " - flags:");
+ if (facet->toporient)
+ fprintf(fp, " top");
+ else
+ fprintf(fp, " bottom");
+ if (facet->simplicial)
+ fprintf(fp, " simplicial");
+ if (facet->tricoplanar)
+ fprintf(fp, " tricoplanar");
+ if (facet->upperdelaunay)
+ fprintf(fp, " upperDelaunay");
+ if (facet->visible)
+ fprintf(fp, " visible");
+ if (facet->newfacet)
+ fprintf(fp, " new");
+ if (facet->tested)
+ fprintf(fp, " tested");
+ if (!facet->good)
+ fprintf(fp, " notG");
+ if (facet->seen)
+ fprintf(fp, " seen");
+ if (facet->coplanar)
+ fprintf(fp, " coplanar");
+ if (facet->mergehorizon)
+ fprintf(fp, " mergehorizon");
+ if (facet->keepcentrum)
+ fprintf(fp, " keepcentrum");
+ if (facet->dupridge)
+ fprintf(fp, " dupridge");
+ if (facet->mergeridge && !facet->mergeridge2)
+ fprintf(fp, " mergeridge1");
+ if (facet->mergeridge2)
+ fprintf(fp, " mergeridge2");
+ if (facet->newmerge)
+ fprintf(fp, " newmerge");
+ if (facet->flipped)
+ fprintf(fp, " flipped");
+ if (facet->notfurthest)
+ fprintf(fp, " notfurthest");
+ if (facet->degenerate)
+ fprintf(fp, " degenerate");
+ if (facet->redundant)
+ fprintf(fp, " redundant");
+ fprintf(fp, "\n");
+ if (facet->isarea)
+ fprintf(fp, " - area: %2.2g\n", facet->f.area);
+ else if (qh NEWfacets && facet->visible && facet->f.replace)
+ fprintf(fp, " - replacement: f%d\n", facet->f.replace->id);
+ else if (facet->newfacet) {
+ if (facet->f.samecycle && facet->f.samecycle != facet)
+ fprintf(fp, " - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
+ }else if (facet->tricoplanar /* !isarea */) {
+ if (facet->f.triowner)
+ fprintf(fp, " - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
+ }else if (facet->f.newcycle)
+ fprintf(fp, " - was horizon to f%d\n", facet->f.newcycle->id);
+ if (facet->nummerge)
+ fprintf(fp, " - merges: %d\n", facet->nummerge);
+ qh_printpointid(fp, " - normal: ", qh hull_dim, facet->normal, -1);
+ fprintf(fp, " - offset: %10.7g\n", facet->offset);
+ if (qh CENTERtype == qh_ASvoronoi || facet->center)
+ qh_printcenter (fp, qh_PRINTfacets, " - center: ", facet);
+#if qh_MAXoutside
+ if (facet->maxoutside > qh DISTround)
+ fprintf(fp, " - maxoutside: %10.7g\n", facet->maxoutside);
+#endif
+ if (!SETempty_(facet->outsideset)) {
+ furthest= (pointT*)qh_setlast(facet->outsideset);
+ if (qh_setsize (facet->outsideset) < 6) {
+ fprintf(fp, " - outside set (furthest p%d):\n", qh_pointid(furthest));
+ FOREACHpoint_(facet->outsideset)
+ qh_printpoint(fp, " ", point);
+ }else if (qh_setsize (facet->outsideset) < 21) {
+ qh_printpoints(fp, " - outside set:", facet->outsideset);
+ }else {
+ fprintf(fp, " - outside set: %d points.", qh_setsize(facet->outsideset));
+ qh_printpoint(fp, " Furthest", furthest);
+ }
+#if !qh_COMPUTEfurthest
+ fprintf(fp, " - furthest distance= %2.2g\n", facet->furthestdist);
+#endif
+ }
+ if (!SETempty_(facet->coplanarset)) {
+ furthest= (pointT*)qh_setlast(facet->coplanarset);
+ if (qh_setsize (facet->coplanarset) < 6) {
+ fprintf(fp, " - coplanar set (furthest p%d):\n", qh_pointid(furthest));
+ FOREACHpoint_(facet->coplanarset)
+ qh_printpoint(fp, " ", point);
+ }else if (qh_setsize (facet->coplanarset) < 21) {
+ qh_printpoints(fp, " - coplanar set:", facet->coplanarset);
+ }else {
+ fprintf(fp, " - coplanar set: %d points.", qh_setsize(facet->coplanarset));
+ qh_printpoint(fp, " Furthest", furthest);
+ }
+ zinc_(Zdistio);
+ qh_distplane (furthest, facet, &dist);
+ fprintf(fp, " furthest distance= %2.2g\n", dist);
+ }
+ qh_printvertices (fp, " - vertices:", facet->vertices);
+ fprintf(fp, " - neighboring facets: ");
+ FOREACHneighbor_(facet) {
+ if (neighbor == qh_MERGEridge)
+ fprintf(fp, " MERGE");
+ else if (neighbor == qh_DUPLICATEridge)
+ fprintf(fp, " DUP");
+ else
+ fprintf(fp, " f%d", neighbor->id);
+ }
+ fprintf(fp, "\n");
+ qh RANDOMdist= qh old_randomdist;
+} /* printfacetheader */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacetridges">-</a>
+
+ qh_printfacetridges( fp, facet )
+ prints ridges of a facet to fp
+
+ notes:
+ ridges printed in neighbor order
+ assumes the ridges exist
+ for 'f' output
+*/
+void qh_printfacetridges(FILE *fp, facetT *facet) {
+ facetT *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+ int numridges= 0;
+
+
+ if (facet->visible && qh NEWfacets) {
+ fprintf(fp, " - ridges (ids may be garbage):");
+ FOREACHridge_(facet->ridges)
+ fprintf(fp, " r%d", ridge->id);
+ fprintf(fp, "\n");
+ }else {
+ fprintf(fp, " - ridges:\n");
+ FOREACHridge_(facet->ridges)
+ ridge->seen= False;
+ if (qh hull_dim == 3) {
+ ridge= SETfirstt_(facet->ridges, ridgeT);
+ while (ridge && !ridge->seen) {
+ ridge->seen= True;
+ qh_printridge(fp, ridge);
+ numridges++;
+ ridge= qh_nextridge3d (ridge, facet, NULL);
+ }
+ }else {
+ FOREACHneighbor_(facet) {
+ FOREACHridge_(facet->ridges) {
+ if (otherfacet_(ridge,facet) == neighbor) {
+ ridge->seen= True;
+ qh_printridge(fp, ridge);
+ numridges++;
+ }
+ }
+ }
+ }
+ if (numridges != qh_setsize (facet->ridges)) {
+ fprintf (fp, " - all ridges:");
+ FOREACHridge_(facet->ridges)
+ fprintf (fp, " r%d", ridge->id);
+ fprintf (fp, "\n");
+ }
+ FOREACHridge_(facet->ridges) {
+ if (!ridge->seen)
+ qh_printridge(fp, ridge);
+ }
+ }
+} /* printfacetridges */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printfacets">-</a>
+
+ qh_printfacets( fp, format, facetlist, facets, printall )
+ prints facetlist and/or facet set in output format
+
+ notes:
+ also used for specialized formats ('FO' and summary)
+ turns off 'Rn' option since want actual numbers
+*/
+void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+ int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+ facetT *facet, **facetp;
+ setT *vertices;
+ coordT *center;
+ realT outerplane, innerplane;
+
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
+ fprintf (qh ferr, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
+ if (format == qh_PRINTnone)
+ ; /* print nothing */
+ else if (format == qh_PRINTaverage) {
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ center= qh_getcenter (vertices);
+ fprintf (fp, "%d 1\n", qh hull_dim);
+ qh_printpointid (fp, NULL, qh hull_dim, center, -1);
+ qh_memfree (center, qh normal_size);
+ qh_settempfree (&vertices);
+ }else if (format == qh_PRINTextremes) {
+ if (qh DELAUNAY)
+ qh_printextremes_d (fp, facetlist, facets, printall);
+ else if (qh hull_dim == 2)
+ qh_printextremes_2d (fp, facetlist, facets, printall);
+ else
+ qh_printextremes (fp, facetlist, facets, printall);
+ }else if (format == qh_PRINToptions)
+ fprintf(fp, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
+ else if (format == qh_PRINTpoints && !qh VORONOI)
+ qh_printpoints_out (fp, facetlist, facets, printall);
+ else if (format == qh_PRINTqhull)
+ fprintf (fp, "%s | %s\n", qh rbox_command, qh qhull_command);
+ else if (format == qh_PRINTsize) {
+ fprintf (fp, "0\n2 ");
+ fprintf (fp, qh_REAL_1, qh totarea);
+ fprintf (fp, qh_REAL_1, qh totvol);
+ fprintf (fp, "\n");
+ }else if (format == qh_PRINTsummary) {
+ qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial,
+ &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ fprintf (fp, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
+ qh num_points + qh_setsize (qh other_points),
+ qh num_vertices, qh num_facets - qh num_visible,
+ qh_setsize (vertices), numfacets, numcoplanars,
+ numfacets - numsimplicial, zzval_(Zdelvertextot),
+ numtricoplanars);
+ qh_settempfree (&vertices);
+ qh_outerinner (NULL, &outerplane, &innerplane);
+ fprintf (fp, qh_REAL_2n, outerplane, innerplane);
+ }else if (format == qh_PRINTvneighbors)
+ qh_printvneighbors (fp, facetlist, facets, printall);
+ else if (qh VORONOI && format == qh_PRINToff)
+ qh_printvoronoi (fp, format, facetlist, facets, printall);
+ else if (qh VORONOI && format == qh_PRINTgeom) {
+ qh_printbegin (fp, format, facetlist, facets, printall);
+ qh_printvoronoi (fp, format, facetlist, facets, printall);
+ qh_printend (fp, format, facetlist, facets, printall);
+ }else if (qh VORONOI
+ && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
+ qh_printvdiagram (fp, format, facetlist, facets, printall);
+ else {
+ qh_printbegin (fp, format, facetlist, facets, printall);
+ FORALLfacet_(facetlist)
+ qh_printafacet (fp, format, facet, printall);
+ FOREACHfacet_(facets)
+ qh_printafacet (fp, format, facet, printall);
+ qh_printend (fp, format, facetlist, facets, printall);
+ }
+ qh RANDOMdist= qh old_randomdist;
+} /* printfacets */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printhelp_degenerate">-</a>
+
+ qh_printhelp_degenerate( fp )
+ prints descriptive message for precision error
+
+ notes:
+ no message if qh_QUICKhelp
+*/
+void qh_printhelp_degenerate(FILE *fp) {
+
+ if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2)
+ fprintf(fp, "\n\
+A Qhull error has occurred. Qhull should have corrected the above\n\
+precision error. Please send the input and all of the output to\n\
+qhull_bug@geom.umn.edu\n");
+ else if (!qh_QUICKhelp) {
+ fprintf(fp, "\n\
+Precision problems were detected during construction of the convex hull.\n\
+This occurs because convex hull algorithms assume that calculations are\n\
+exact, but floating-point arithmetic has roundoff errors.\n\
+\n\
+To correct for precision problems, do not use 'Q0'. By default, Qhull\n\
+selects 'C-0' or 'Qx' and merges non-convex facets. With option 'QJ',\n\
+Qhull joggles the input to prevent precision problems. See \"Imprecision\n\
+in Qhull\" (qh-impre.htm).\n\
+\n\
+If you use 'Q0', the output may include\n\
+coplanar ridges, concave ridges, and flipped facets. In 4-d and higher,\n\
+Qhull may produce a ridge with four neighbors or two facets with the same \n\
+vertices. Qhull reports these events when they occur. It stops when a\n\
+concave ridge, flipped facet, or duplicate facet occurs.\n");
+#if REALfloat
+ fprintf (fp, "\
+\n\
+Qhull is currently using single precision arithmetic. The following\n\
+will probably remove the precision problems:\n\
+ - recompile qhull for double precision (#define REALfloat 0 in user.h).\n");
+#endif
+ if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
+ fprintf( fp, "\
+\n\
+When computing the Delaunay triangulation of coordinates > 1.0,\n\
+ - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
+ if (qh DELAUNAY && !qh ATinfinity)
+ fprintf( fp, "\
+When computing the Delaunay triangulation:\n\
+ - use 'Qz' to add a point at-infinity. This reduces precision problems.\n");
+
+ fprintf(fp, "\
+\n\
+If you need triangular output:\n\
+ - use option 'Qt' to triangulate the output\n\
+ - use option 'QJ' to joggle the input points and remove precision errors\n\
+ - use option 'Ft'. It triangulates non-simplicial facets with added points.\n\
+\n\
+If you must use 'Q0',\n\
+try one or more of the following options. They can not guarantee an output.\n\
+ - use 'QbB' to scale the input to a cube.\n\
+ - use 'Po' to produce output and prevent partitioning for flipped facets\n\
+ - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
+ - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
+ - options 'Qf', 'Qbb', and 'QR0' may also help\n",
+ qh DISTround);
+ fprintf(fp, "\
+\n\
+To guarantee simplicial output:\n\
+ - use option 'Qt' to triangulate the output\n\
+ - use option 'QJ' to joggle the input points and remove precision errors\n\
+ - use option 'Ft' to triangulate the output by adding points\n\
+ - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
+");
+ }
+} /* printhelp_degenerate */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printhelp_singular">-</a>
+
+ qh_printhelp_singular( fp )
+ prints descriptive message for singular input
+*/
+void qh_printhelp_singular(FILE *fp) {
+ facetT *facet;
+ vertexT *vertex, **vertexp;
+ realT min, max, *coord, dist;
+ int i,k;
+
+ fprintf(fp, "\n\
+The input to qhull appears to be less than %d dimensional, or a\n\
+computation has overflowed.\n\n\
+Qhull could not construct a clearly convex simplex from points:\n",
+ qh hull_dim);
+ qh_printvertexlist (fp, "", qh facet_list, NULL, qh_ALL);
+ if (!qh_QUICKhelp)
+ fprintf(fp, "\n\
+The center point is coplanar with a facet, or a vertex is coplanar\n\
+with a neighboring facet. The maximum round off error for\n\
+computing distances is %2.2g. The center point, facets and distances\n\
+to the center point are as follows:\n\n", qh DISTround);
+ qh_printpointid (fp, "center point", qh hull_dim, qh interior_point, -1);
+ fprintf (fp, "\n");
+ FORALLfacets {
+ fprintf (fp, "facet");
+ FOREACHvertex_(facet->vertices)
+ fprintf (fp, " p%d", qh_pointid(vertex->point));
+ zinc_(Zdistio);
+ qh_distplane(qh interior_point, facet, &dist);
+ fprintf (fp, " distance= %4.2g\n", dist);
+ }
+ if (!qh_QUICKhelp) {
+ if (qh HALFspace)
+ fprintf (fp, "\n\
+These points are the dual of the given halfspaces. They indicate that\n\
+the intersection is degenerate.\n");
+ fprintf (fp,"\n\
+These points either have a maximum or minimum x-coordinate, or\n\
+they maximize the determinant for k coordinates. Trial points\n\
+are first selected from points that maximize a coordinate.\n");
+ if (qh hull_dim >= qh_INITIALmax)
+ fprintf (fp, "\n\
+Because of the high dimension, the min x-coordinate and max-coordinate\n\
+points are used if the determinant is non-zero. Option 'Qs' will\n\
+do a better, though much slower, job. Instead of 'Qs', you can change\n\
+the points by randomly rotating the input with 'QR0'.\n");
+ }
+ fprintf (fp, "\nThe min and max coordinates for each dimension are:\n");
+ for (k=0; k < qh hull_dim; k++) {
+ min= REALmax;
+ max= -REALmin;
+ for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
+ maximize_(max, *coord);
+ minimize_(min, *coord);
+ }
+ fprintf (fp, " %d: %8.4g %8.4g difference= %4.4g\n", k, min, max, max-min);
+ }
+ if (!qh_QUICKhelp) {
+ fprintf (fp, "\n\
+If the input should be full dimensional, you have several options that\n\
+may determine an initial simplex:\n\
+ - use 'QJ' to joggle the input and make it full dimensional\n\
+ - use 'QbB' to scale the points to the unit cube\n\
+ - use 'QR0' to randomly rotate the input for different maximum points\n\
+ - use 'Qs' to search all points for the initial simplex\n\
+ - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
+ - trace execution with 'T3' to see the determinant for each point.\n",
+ qh DISTround);
+#if REALfloat
+ fprintf (fp, "\
+ - recompile qhull for double precision (#define REALfloat 0 in qhull.h).\n");
+#endif
+ fprintf (fp, "\n\
+If the input is lower dimensional:\n\
+ - use 'QJ' to joggle the input and make it full dimensional\n\
+ - use 'Qbk:0Bk:0' to delete coordinate k from the input. You should\n\
+ pick the coordinate with the least range. The hull will have the\n\
+ correct topology.\n\
+ - determine the flat containing the points, rotate the points\n\
+ into a coordinate plane, and delete the other coordinates.\n\
+ - add one or more points to make the input full dimensional.\n\
+");
+ if (qh DELAUNAY && !qh ATinfinity)
+ fprintf (fp, "\n\n\
+This is a Delaunay triangulation and the input is co-circular or co-spherical:\n\
+ - use 'Qz' to add a point \"at infinity\" (i.e., above the paraboloid)\n\
+ - or use 'QJ' to joggle the input and avoid co-circular data\n");
+ }
+} /* printhelp_singular */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printhyperplaneintersection">-</a>
+
+ qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
+ print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
+*/
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+ setT *vertices, realT color[3]) {
+ realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
+ vertexT *vertex, **vertexp;
+ int i, k;
+ boolT nearzero1, nearzero2;
+
+ costheta= qh_getangle(facet1->normal, facet2->normal);
+ denominator= 1 - costheta * costheta;
+ i= qh_setsize(vertices);
+ if (qh hull_dim == 3)
+ fprintf(fp, "VECT 1 %d 1 %d 1 ", i, i);
+ else if (qh hull_dim == 4 && qh DROPdim >= 0)
+ fprintf(fp, "OFF 3 1 1 ");
+ else
+ qh printoutvar++;
+ fprintf (fp, "# intersect f%d f%d\n", facet1->id, facet2->id);
+ mindenom= 1 / (10.0 * qh MAXabs_coord);
+ FOREACHvertex_(vertices) {
+ zadd_(Zdistio, 2);
+ qh_distplane(vertex->point, facet1, &dist1);
+ qh_distplane(vertex->point, facet2, &dist2);
+ s= qh_divzero (-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
+ t= qh_divzero (-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
+ if (nearzero1 || nearzero2)
+ s= t= 0.0;
+ for(k= qh hull_dim; k--; )
+ p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
+ if (qh PRINTdim <= 3) {
+ qh_projectdim3 (p, p);
+ fprintf(fp, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
+ }else
+ fprintf(fp, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
+ if (nearzero1+nearzero2)
+ fprintf (fp, "p%d (coplanar facets)\n", qh_pointid (vertex->point));
+ else
+ fprintf (fp, "projected p%d\n", qh_pointid (vertex->point));
+ }
+ if (qh hull_dim == 3)
+ fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+ else if (qh hull_dim == 4 && qh DROPdim >= 0)
+ fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printhyperplaneintersection */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printline3geom">-</a>
+
+ qh_printline3geom( fp, pointA, pointB, color )
+ prints a line as a VECT
+ prints 0's for qh.DROPdim
+
+ notes:
+ if pointA == pointB,
+ it's a 1 point VECT
+*/
+void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
+ int k;
+ realT pA[4], pB[4];
+
+ qh_projectdim3(pointA, pA);
+ qh_projectdim3(pointB, pB);
+ if ((fabs(pA[0] - pB[0]) > 1e-3) ||
+ (fabs(pA[1] - pB[1]) > 1e-3) ||
+ (fabs(pA[2] - pB[2]) > 1e-3)) {
+ fprintf (fp, "VECT 1 2 1 2 1\n");
+ for (k= 0; k < 3; k++)
+ fprintf (fp, "%8.4g ", pB[k]);
+ fprintf (fp, " # p%d\n", qh_pointid (pointB));
+ }else
+ fprintf (fp, "VECT 1 1 1 1 1\n");
+ for (k=0; k < 3; k++)
+ fprintf (fp, "%8.4g ", pA[k]);
+ fprintf (fp, " # p%d\n", qh_pointid (pointA));
+ fprintf (fp, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
+}
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printneighborhood">-</a>
+
+ qh_printneighborhood( fp, format, facetA, facetB, printall )
+ print neighborhood of one or two facets
+
+ notes:
+ calls qh_findgood_all()
+ bumps qh.visit_id
+*/
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall) {
+ facetT *neighbor, **neighborp, *facet;
+ setT *facets;
+
+ if (format == qh_PRINTnone)
+ return;
+ qh_findgood_all (qh facet_list);
+ if (facetA == facetB)
+ facetB= NULL;
+ facets= qh_settemp (2*(qh_setsize (facetA->neighbors)+1));
+ qh visit_id++;
+ for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
+ if (facet->visitid != qh visit_id) {
+ facet->visitid= qh visit_id;
+ qh_setappend (&facets, facet);
+ }
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid == qh visit_id)
+ continue;
+ neighbor->visitid= qh visit_id;
+ if (printall || !qh_skipfacet (neighbor))
+ qh_setappend (&facets, neighbor);
+ }
+ }
+ qh_printfacets (fp, format, NULL, facets, printall);
+ qh_settempfree (&facets);
+} /* printneighborhood */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printpoint">-</a>
+
+ qh_printpoint( fp, string, point )
+ qh_printpointid( fp, string, dim, point, id )
+ prints the coordinates of a point
+
+ returns:
+ if string is defined
+ prints 'string p%d' (skips p%d if id=-1)
+
+ notes:
+ nop if point is NULL
+ prints id unless it is undefined (-1)
+*/
+void qh_printpoint(FILE *fp, char *string, pointT *point) {
+ int id= qh_pointid( point);
+
+ qh_printpointid( fp, string, qh hull_dim, point, id);
+} /* printpoint */
+
+void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id) {
+ int k;
+ realT r; /*bug fix*/
+
+ if (!point)
+ return;
+ if (string) {
+ fputs (string, fp);
+ if (id != -1)
+ fprintf(fp, " p%d: ", id);
+ }
+ for(k= dim; k--; ) {
+ r= *point++;
+ if (string)
+ fprintf(fp, " %8.4g", r);
+ else
+ fprintf(fp, qh_REAL_1, r);
+ }
+ fprintf(fp, "\n");
+} /* printpointid */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printpoint3">-</a>
+
+ qh_printpoint3( fp, point )
+ prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
+*/
+void qh_printpoint3 (FILE *fp, pointT *point) {
+ int k;
+ realT p[4];
+
+ qh_projectdim3 (point, p);
+ for (k=0; k < 3; k++)
+ fprintf (fp, "%8.4g ", p[k]);
+ fprintf (fp, " # p%d\n", qh_pointid (point));
+} /* printpoint3 */
+
+/*----------------------------------------
+-printpoints- print pointids for a set of points starting at index
+ see geom.c
+*/
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printpoints_out">-</a>
+
+ qh_printpoints_out( fp, facetlist, facets, printall )
+ prints vertices, coplanar/inside points, for facets by their point coordinates
+ allows qh.CDDoutput
+
+ notes:
+ same format as qhull input
+ if no coplanar/interior points,
+ same order as qh_printextremes
+*/
+void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+ int allpoints= qh num_points + qh_setsize (qh other_points);
+ int numpoints=0, point_i, point_n;
+ setT *vertices, *points;
+ facetT *facet, **facetp;
+ pointT *point, **pointp;
+ vertexT *vertex, **vertexp;
+ int id;
+
+ points= qh_settemp (allpoints);
+ qh_setzero (points, 0, allpoints);
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ FOREACHvertex_(vertices) {
+ id= qh_pointid (vertex->point);
+ if (id >= 0)
+ SETelem_(points, id)= vertex->point;
+ }
+ if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
+ FORALLfacet_(facetlist) {
+ if (!printall && qh_skipfacet(facet))
+ continue;
+ FOREACHpoint_(facet->coplanarset) {
+ id= qh_pointid (point);
+ if (id >= 0)
+ SETelem_(points, id)= point;
+ }
+ }
+ FOREACHfacet_(facets) {
+ if (!printall && qh_skipfacet(facet))
+ continue;
+ FOREACHpoint_(facet->coplanarset) {
+ id= qh_pointid (point);
+ if (id >= 0)
+ SETelem_(points, id)= point;
+ }
+ }
+ }
+ qh_settempfree (&vertices);
+ FOREACHpoint_i_(points) {
+ if (point)
+ numpoints++;
+ }
+ if (qh CDDoutput)
+ fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+ qh qhull_command, numpoints, qh hull_dim + 1);
+ else
+ fprintf (fp, "%d\n%d\n", qh hull_dim, numpoints);
+ FOREACHpoint_i_(points) {
+ if (point) {
+ if (qh CDDoutput)
+ fprintf (fp, "1 ");
+ qh_printpoint (fp, NULL, point);
+ }
+ }
+ if (qh CDDoutput)
+ fprintf (fp, "end\n");
+ qh_settempfree (&points);
+} /* printpoints_out */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printpointvect">-</a>
+
+ qh_printpointvect( fp, point, normal, center, radius, color )
+ prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
+*/
+void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
+ realT diff[4], pointA[4];
+ int k;
+
+ for (k= qh hull_dim; k--; ) {
+ if (center)
+ diff[k]= point[k]-center[k];
+ else if (normal)
+ diff[k]= normal[k];
+ else
+ diff[k]= 0;
+ }
+ if (center)
+ qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
+ for (k= qh hull_dim; k--; )
+ pointA[k]= point[k]+diff[k] * radius;
+ qh_printline3geom (fp, point, pointA, color);
+} /* printpointvect */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printpointvect2">-</a>
+
+ qh_printpointvect2( fp, point, normal, center, radius )
+ prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
+*/
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
+ realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
+
+ qh_printpointvect (fp, point, normal, center, radius, red);
+ qh_printpointvect (fp, point, normal, center, -radius, yellow);
+} /* printpointvect2 */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printridge">-</a>
+
+ qh_printridge( fp, ridge )
+ prints the information in a ridge
+
+ notes:
+ for qh_printfacetridges()
+*/
+void qh_printridge(FILE *fp, ridgeT *ridge) {
+
+ fprintf(fp, " - r%d", ridge->id);
+ if (ridge->tested)
+ fprintf (fp, " tested");
+ if (ridge->nonconvex)
+ fprintf (fp, " nonconvex");
+ fprintf (fp, "\n");
+ qh_printvertices (fp, " vertices:", ridge->vertices);
+ if (ridge->top && ridge->bottom)
+ fprintf(fp, " between f%d and f%d\n",
+ ridge->top->id, ridge->bottom->id);
+} /* printridge */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printspheres">-</a>
+
+ qh_printspheres( fp, vertices, radius )
+ prints 3-d vertices as OFF spheres
+
+ notes:
+ inflated octahedron from Stuart Levy earth/mksphere2
+*/
+void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
+ vertexT *vertex, **vertexp;
+
+ qh printoutnum++;
+ fprintf (fp, "{appearance {-edge -normal normscale 0} {\n\
+INST geom {define vsphere OFF\n\
+18 32 48\n\
+\n\
+0 0 1\n\
+1 0 0\n\
+0 1 0\n\
+-1 0 0\n\
+0 -1 0\n\
+0 0 -1\n\
+0.707107 0 0.707107\n\
+0 -0.707107 0.707107\n\
+0.707107 -0.707107 0\n\
+-0.707107 0 0.707107\n\
+-0.707107 -0.707107 0\n\
+0 0.707107 0.707107\n\
+-0.707107 0.707107 0\n\
+0.707107 0.707107 0\n\
+0.707107 0 -0.707107\n\
+0 0.707107 -0.707107\n\
+-0.707107 0 -0.707107\n\
+0 -0.707107 -0.707107\n\
+\n\
+3 0 6 11\n\
+3 0 7 6 \n\
+3 0 9 7 \n\
+3 0 11 9\n\
+3 1 6 8 \n\
+3 1 8 14\n\
+3 1 13 6\n\
+3 1 14 13\n\
+3 2 11 13\n\
+3 2 12 11\n\
+3 2 13 15\n\
+3 2 15 12\n\
+3 3 9 12\n\
+3 3 10 9\n\
+3 3 12 16\n\
+3 3 16 10\n\
+3 4 7 10\n\
+3 4 8 7\n\
+3 4 10 17\n\
+3 4 17 8\n\
+3 5 14 17\n\
+3 5 15 14\n\
+3 5 16 15\n\
+3 5 17 16\n\
+3 6 13 11\n\
+3 7 8 6\n\
+3 9 10 7\n\
+3 11 12 9\n\
+3 14 8 17\n\
+3 15 13 14\n\
+3 16 12 15\n\
+3 17 10 16\n} transforms { TLIST\n");
+ FOREACHvertex_(vertices) {
+ fprintf(fp, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
+ radius, vertex->id, radius, radius);
+ qh_printpoint3 (fp, vertex->point);
+ fprintf (fp, "1\n");
+ }
+ fprintf (fp, "}}}\n");
+} /* printspheres */
+
+
+/*----------------------------------------------
+-printsummary-
+ see qhull.c
+*/
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvdiagram">-</a>
+
+ qh_printvdiagram( fp, format, facetlist, facets, printall )
+ print voronoi diagram
+ # of pairs of input sites
+ #indices site1 site2 vertex1 ...
+
+ sites indexed by input point id
+ point 0 is the first input point
+ vertices indexed by 'o' and 'p' order
+ vertex 0 is the 'vertex-at-infinity'
+ vertex 1 is the first Voronoi vertex
+
+ see:
+ qh_printvoronoi()
+ qh_eachvoronoi_all()
+
+ notes:
+ if all facets are upperdelaunay,
+ prints upper hull (furthest-site Voronoi diagram)
+*/
+void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+ setT *vertices;
+ int totcount, numcenters;
+ boolT islower;
+ qh_RIDGE innerouter= qh_RIDGEall;
+ printvridgeT printvridge= NULL;
+
+ if (format == qh_PRINTvertices) {
+ innerouter= qh_RIDGEall;
+ printvridge= qh_printvridge;
+ }else if (format == qh_PRINTinner) {
+ innerouter= qh_RIDGEinner;
+ printvridge= qh_printvnorm;
+ }else if (format == qh_PRINTouter) {
+ innerouter= qh_RIDGEouter;
+ printvridge= qh_printvnorm;
+ }else {
+ fprintf(qh ferr, "qh_printvdiagram: unknown print format %d.\n", format);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
+ totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
+ fprintf (fp, "%d\n", totcount);
+ totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
+ qh_settempfree (&vertices);
+#if 0 /* for testing qh_eachvoronoi_all */
+ fprintf (fp, "\n");
+ totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
+ fprintf (fp, "%d\n", totcount);
+#endif
+} /* printvdiagram */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvdiagram2">-</a>
+
+ qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
+ visit all pairs of input sites (vertices) for selected Voronoi vertices
+ vertices may include NULLs
+
+ innerouter:
+ qh_RIDGEall print inner ridges (bounded) and outer ridges (unbounded)
+ qh_RIDGEinner print only inner ridges
+ qh_RIDGEouter print only outer ridges
+
+ inorder:
+ print 3-d Voronoi vertices in order
+
+ assumes:
+ qh_markvoronoi marked facet->visitid for Voronoi vertices
+ all facet->seen= False
+ all facet->seen2= True
+
+ returns:
+ total number of Voronoi ridges
+ if printvridge,
+ calls printvridge( fp, vertex, vertexA, centers) for each ridge
+ [see qh_eachvoronoi()]
+
+ see:
+ qh_eachvoronoi_all()
+*/
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
+ int totcount= 0;
+ int vertex_i, vertex_n;
+ vertexT *vertex;
+
+ FORALLvertices
+ vertex->seen= False;
+ FOREACHvertex_i_(vertices) {
+ if (vertex) {
+ if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+ continue;
+ totcount += qh_eachvoronoi (fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
+ }
+ }
+ return totcount;
+} /* printvdiagram2 */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvertex">-</a>
+
+ qh_printvertex( fp, vertex )
+ prints the information in a vertex
+*/
+void qh_printvertex(FILE *fp, vertexT *vertex) {
+ pointT *point;
+ int k, count= 0;
+ facetT *neighbor, **neighborp;
+ realT r; /*bug fix*/
+
+ if (!vertex) {
+ fprintf (fp, " NULLvertex\n");
+ return;
+ }
+ fprintf(fp, "- p%d (v%d):", qh_pointid(vertex->point), vertex->id);
+ point= vertex->point;
+ if (point) {
+ for(k= qh hull_dim; k--; ) {
+ r= *point++;
+ fprintf(fp, " %5.2g", r);
+ }
+ }
+ if (vertex->deleted)
+ fprintf(fp, " deleted");
+ if (vertex->delridge)
+ fprintf (fp, " ridgedeleted");
+ fprintf(fp, "\n");
+ if (vertex->neighbors) {
+ fprintf(fp, " neighbors:");
+ FOREACHneighbor_(vertex) {
+ if (++count % 100 == 0)
+ fprintf (fp, "\n ");
+ fprintf(fp, " f%d", neighbor->id);
+ }
+ fprintf(fp, "\n");
+ }
+} /* printvertex */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvertexlist">-</a>
+
+ qh_printvertexlist( fp, string, facetlist, facets, printall )
+ prints vertices used by a facetlist or facet set
+ tests qh_skipfacet() if !printall
+*/
+void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
+ setT *facets, boolT printall) {
+ vertexT *vertex, **vertexp;
+ setT *vertices;
+
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ fputs (string, fp);
+ FOREACHvertex_(vertices)
+ qh_printvertex(fp, vertex);
+ qh_settempfree (&vertices);
+} /* printvertexlist */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvertices">-</a>
+
+ qh_printvertices( fp, string, vertices )
+ prints vertices in a set
+*/
+void qh_printvertices(FILE *fp, char* string, setT *vertices) {
+ vertexT *vertex, **vertexp;
+
+ fputs (string, fp);
+ FOREACHvertex_(vertices)
+ fprintf (fp, " p%d (v%d)", qh_pointid(vertex->point), vertex->id);
+ fprintf(fp, "\n");
+} /* printvertices */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvneighbors">-</a>
+
+ qh_printvneighbors( fp, facetlist, facets, printall )
+ print vertex neighbors of vertices in facetlist and facets ('FN')
+
+ notes:
+ qh_countfacets clears facet->visitid for non-printed facets
+
+ design:
+ collect facet count and related statistics
+ if necessary, build neighbor sets for each vertex
+ collect vertices in facetlist and facets
+ build a point array for point->vertex and point->coplanar facet
+ for each point
+ list vertex neighbors or coplanar facet
+*/
+void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
+ int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
+ setT *vertices, *vertex_points, *coplanar_points;
+ int numpoints= qh num_points + qh_setsize (qh other_points);
+ vertexT *vertex, **vertexp;
+ int vertex_i, vertex_n;
+ facetT *facet, **facetp, *neighbor, **neighborp;
+ pointT *point, **pointp;
+
+ qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial,
+ &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* sets facet->visitid */
+ fprintf (fp, "%d\n", numpoints);
+ qh_vertexneighbors();
+ vertices= qh_facetvertices (facetlist, facets, printall);
+ vertex_points= qh_settemp (numpoints);
+ coplanar_points= qh_settemp (numpoints);
+ qh_setzero (vertex_points, 0, numpoints);
+ qh_setzero (coplanar_points, 0, numpoints);
+ FOREACHvertex_(vertices)
+ qh_point_add (vertex_points, vertex->point, vertex);
+ FORALLfacet_(facetlist) {
+ FOREACHpoint_(facet->coplanarset)
+ qh_point_add (coplanar_points, point, facet);
+ }
+ FOREACHfacet_(facets) {
+ FOREACHpoint_(facet->coplanarset)
+ qh_point_add (coplanar_points, point, facet);
+ }
+ FOREACHvertex_i_(vertex_points) {
+ if (vertex) {
+ numneighbors= qh_setsize (vertex->neighbors);
+ fprintf (fp, "%d", numneighbors);
+ if (qh hull_dim == 3)
+ qh_order_vertexneighbors (vertex);
+ else if (qh hull_dim >= 4)
+ qsort (SETaddr_(vertex->neighbors, facetT), numneighbors,
+ sizeof (facetT *), qh_compare_facetvisit);
+ FOREACHneighbor_(vertex)
+ fprintf (fp, " %d",
+ neighbor->visitid ? neighbor->visitid - 1 : - neighbor->id);
+ fprintf (fp, "\n");
+ }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
+ fprintf (fp, "1 %d\n",
+ facet->visitid ? facet->visitid - 1 : - facet->id);
+ else
+ fprintf (fp, "0\n");
+ }
+ qh_settempfree (&coplanar_points);
+ qh_settempfree (&vertex_points);
+ qh_settempfree (&vertices);
+} /* printvneighbors */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvoronoi">-</a>
+
+ qh_printvoronoi( fp, format, facetlist, facets, printall )
+ print voronoi diagram in 'o' or 'G' format
+ for 'o' format
+ prints voronoi centers for each facet and for infinity
+ for each vertex, lists ids of printed facets or infinity
+ assumes facetlist and facets are disjoint
+ for 'G' format
+ prints an OFF object
+ adds a 0 coordinate to center
+ prints infinity but does not list in vertices
+
+ see:
+ qh_printvdiagram()
+
+ notes:
+ if 'o',
+ prints a line for each point except "at-infinity"
+ if all facets are upperdelaunay,
+ reverses lower and upper hull
+*/
+void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+ int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
+ facetT *facet, **facetp, *neighbor, **neighborp;
+ setT *vertices;
+ vertexT *vertex;
+ boolT islower;
+ unsigned int numfacets= (unsigned int) qh num_facets;
+
+ vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
+ FOREACHvertex_i_(vertices) {
+ if (vertex) {
+ numvertices++;
+ numneighbors = numinf = 0;
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid == 0)
+ numinf= 1;
+ else if (neighbor->visitid < numfacets)
+ numneighbors++;
+ }
+ if (numinf && !numneighbors) {
+ SETelem_(vertices, vertex_i)= NULL;
+ numvertices--;
+ }
+ }
+ }
+ if (format == qh_PRINTgeom)
+ fprintf (fp, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
+ numcenters, numvertices);
+ else
+ fprintf (fp, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
+ if (format == qh_PRINTgeom) {
+ for (k= qh hull_dim-1; k--; )
+ fprintf (fp, qh_REAL_1, 0.0);
+ fprintf (fp, " 0 # infinity not used\n");
+ }else {
+ for (k= qh hull_dim-1; k--; )
+ fprintf (fp, qh_REAL_1, qh_INFINITE);
+ fprintf (fp, "\n");
+ }
+ FORALLfacet_(facetlist) {
+ if (facet->visitid && facet->visitid < numfacets) {
+ if (format == qh_PRINTgeom)
+ fprintf (fp, "# %d f%d\n", vid++, facet->id);
+ qh_printcenter (fp, format, NULL, facet);
+ }
+ }
+ FOREACHfacet_(facets) {
+ if (facet->visitid && facet->visitid < numfacets) {
+ if (format == qh_PRINTgeom)
+ fprintf (fp, "# %d f%d\n", vid++, facet->id);
+ qh_printcenter (fp, format, NULL, facet);
+ }
+ }
+ FOREACHvertex_i_(vertices) {
+ numneighbors= 0;
+ numinf=0;
+ if (vertex) {
+ if (qh hull_dim == 3)
+ qh_order_vertexneighbors(vertex);
+ else if (qh hull_dim >= 4)
+ qsort (SETaddr_(vertex->neighbors, vertexT),
+ qh_setsize (vertex->neighbors),
+ sizeof (facetT *), qh_compare_facetvisit);
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid == 0)
+ numinf= 1;
+ else if (neighbor->visitid < numfacets)
+ numneighbors++;
+ }
+ }
+ if (format == qh_PRINTgeom) {
+ if (vertex) {
+ fprintf (fp, "%d", numneighbors);
+ if (vertex) {
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid && neighbor->visitid < numfacets)
+ fprintf (fp, " %d", neighbor->visitid);
+ }
+ }
+ fprintf (fp, " # p%d (v%d)\n", vertex_i, vertex->id);
+ }else
+ fprintf (fp, " # p%d is coplanar or isolated\n", vertex_i);
+ }else {
+ if (numinf)
+ numneighbors++;
+ fprintf (fp, "%d", numneighbors);
+ if (vertex) {
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid == 0) {
+ if (numinf) {
+ numinf= 0;
+ fprintf (fp, " %d", neighbor->visitid);
+ }
+ }else if (neighbor->visitid < numfacets)
+ fprintf (fp, " %d", neighbor->visitid);
+ }
+ }
+ fprintf (fp, "\n");
+ }
+ }
+ if (format == qh_PRINTgeom)
+ fprintf (fp, "}\n");
+ qh_settempfree (&vertices);
+} /* printvoronoi */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvnorm">-</a>
+
+ qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
+ print one separating plane of the Voronoi diagram for a pair of input sites
+ unbounded==True if centers includes vertex-at-infinity
+
+ assumes:
+ qh_ASvoronoi and qh_vertexneighbors() already set
+
+ see:
+ qh_printvdiagram()
+ qh_eachvoronoi()
+*/
+void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+ pointT *normal;
+ realT offset;
+ int k;
+
+ normal= qh_detvnorm (vertex, vertexA, centers, &offset);
+ fprintf (fp, "%d %d %d ",
+ 2+qh hull_dim, qh_pointid (vertex->point), qh_pointid (vertexA->point));
+ for (k= 0; k< qh hull_dim-1; k++)
+ fprintf (fp, qh_REAL_1, normal[k]);
+ fprintf (fp, qh_REAL_1, offset);
+ fprintf (fp, "\n");
+} /* printvnorm */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="printvridge">-</a>
+
+ qh_printvridge( fp, vertex, vertexA, centers, unbounded )
+ print one ridge of the Voronoi diagram for a pair of input sites
+ unbounded==True if centers includes vertex-at-infinity
+
+ see:
+ qh_printvdiagram()
+
+ notes:
+ the user may use a different function
+*/
+void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+ facetT *facet, **facetp;
+
+ fprintf (fp, "%d %d %d", qh_setsize (centers)+2,
+ qh_pointid (vertex->point), qh_pointid (vertexA->point));
+ FOREACHfacet_(centers)
+ fprintf (fp, " %d", facet->visitid);
+ fprintf (fp, "\n");
+} /* printvridge */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="projectdim3">-</a>
+
+ qh_projectdim3( source, destination )
+ project 2-d 3-d or 4-d point to a 3-d point
+ uses qh.DROPdim and qh.hull_dim
+ source and destination may be the same
+
+ notes:
+ allocate 4 elements to destination just in case
+*/
+void qh_projectdim3 (pointT *source, pointT *destination) {
+ int i,k;
+
+ for (k= 0, i=0; k < qh hull_dim; k++) {
+ if (qh hull_dim == 4) {
+ if (k != qh DROPdim)
+ destination[i++]= source[k];
+ }else if (k == qh DROPdim)
+ destination[i++]= 0;
+ else
+ destination[i++]= source[k];
+ }
+ while (i < 3)
+ destination[i++]= 0.0;
+} /* projectdim3 */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="readfeasible">-</a>
+
+ qh_readfeasible( dim, remainder )
+ read feasible point from remainder string and qh.fin
+
+ returns:
+ number of lines read from qh.fin
+ sets qh.FEASIBLEpoint with malloc'd coordinates
+
+ notes:
+ checks for qh.HALFspace
+ assumes dim > 1
+
+ see:
+ qh_setfeasible
+*/
+int qh_readfeasible (int dim, char *remainder) {
+ boolT isfirst= True;
+ int linecount= 0, tokcount= 0;
+ char *s, *t, firstline[qh_MAXfirst+1];
+ coordT *coords, value;
+
+ if (!qh HALFspace) {
+ fprintf (qh ferr, "qhull input error: feasible point (dim 1 coords) is only valid for halfspace intersection\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh feasible_string)
+ fprintf (qh ferr, "qhull input warning: feasible point (dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
+ if (!(qh feasible_point= (coordT*)malloc (dim* sizeof(coordT)))) {
+ fprintf(qh ferr, "qhull error: insufficient memory for feasible point\n");
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ coords= qh feasible_point;
+ while ((s= (isfirst ? remainder : fgets(firstline, qh_MAXfirst, qh fin)))) {
+ if (isfirst)
+ isfirst= False;
+ else
+ linecount++;
+ while (*s) {
+ while (isspace(*s))
+ s++;
+ value= qh_strtod (s, &t);
+ if (s == t)
+ break;
+ s= t;
+ *(coords++)= value;
+ if (++tokcount == dim) {
+ while (isspace (*s))
+ s++;
+ qh_strtod (s, &t);
+ if (s != t) {
+ fprintf (qh ferr, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
+ s);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ return linecount;
+ }
+ }
+ }
+ fprintf (qh ferr, "qhull input error: only %d coordinates. Could not read %d-d feasible point.\n",
+ tokcount, dim);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ return 0;
+} /* readfeasible */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="readpoints">-</a>
+
+ qh_readpoints( numpoints, dimension, ismalloc )
+ read points from qh.fin into qh.first_point, qh.num_points
+ qh.fin is lines of coordinates, one per vertex, first line number of points
+ if 'rbox D4',
+ gives message
+ if qh.ATinfinity,
+ adds point-at-infinity for Delaunay triangulations
+
+ returns:
+ number of points, array of point coordinates, dimension, ismalloc True
+ if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
+ and clears qh.PROJECTdelaunay
+ if qh.HALFspace, reads optional feasible point, reads halfspaces,
+ converts to dual.
+
+ for feasible point in "cdd format" in 3-d:
+ 3 1
+ coordinates
+ comments
+ begin
+ n 4 real/integer
+ ...
+ end
+
+ notes:
+ dimension will change in qh_initqhull_globals if qh.PROJECTinput
+ uses malloc() since qh_mem not initialized
+ FIXUP: this routine needs rewriting
+*/
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
+ coordT *points, *coords, *infinity= NULL;
+ realT paraboloid, maxboloid= -REALmax, value;
+ realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
+ char *s, *t, firstline[qh_MAXfirst+1];
+ int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
+ int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
+ int tokcount= 0, linecount=0, maxcount, coordcount=0;
+ boolT islong, isfirst= True, wasbegin= False;
+ boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
+
+ if (qh CDDinput) {
+ while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
+ linecount++;
+ if (qh HALFspace && linecount == 1 && isdigit(*s)) {
+ dimfeasible= qh_strtol (s, &s);
+ while (isspace(*s))
+ s++;
+ if (qh_strtol (s, &s) == 1)
+ linecount += qh_readfeasible (dimfeasible, s);
+ else
+ dimfeasible= 0;
+ }else if (!memcmp (firstline, "begin", 5) || !memcmp (firstline, "BEGIN", 5))
+ break;
+ else if (!*qh rbox_command)
+ strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+ }
+ if (!s) {
+ fprintf (qh ferr, "qhull input error: missing \"begin\" for cdd-formated input\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ }
+ while(!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
+ linecount++;
+ if (!memcmp (s, "begin", 5) || !memcmp (s, "BEGIN", 5))
+ wasbegin= True;
+ while (*s) {
+ while (isspace(*s))
+ s++;
+ if (!*s)
+ break;
+ if (!isdigit(*s)) {
+ if (!*qh rbox_command) {
+ strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+ firsttext= linecount;
+ }
+ break;
+ }
+ if (!diminput)
+ diminput= qh_strtol (s, &s);
+ else {
+ numinput= qh_strtol (s, &s);
+ if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
+ linecount += qh_readfeasible (diminput, s); /* checks if ok */
+ dimfeasible= diminput;
+ diminput= numinput= 0;
+ }else
+ break;
+ }
+ }
+ }
+ if (!s) {
+ fprintf(qh ferr, "qhull input error: short input file. Did not find dimension and number of points\n");
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (diminput > numinput) {
+ tempi= diminput; /* exchange dim and n, e.g., for cdd input format */
+ diminput= numinput;
+ numinput= tempi;
+ }
+ if (diminput < 2) {
+ fprintf(qh ferr,"qhull input error: dimension %d (first number) should be at least 2\n",
+ diminput);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (isdelaunay) {
+ qh PROJECTdelaunay= False;
+ if (qh CDDinput)
+ *dimension= diminput;
+ else
+ *dimension= diminput+1;
+ *numpoints= numinput;
+ if (qh ATinfinity)
+ (*numpoints)++;
+ }else if (qh HALFspace) {
+ *dimension= diminput - 1;
+ *numpoints= numinput;
+ if (diminput < 3) {
+ fprintf(qh ferr,"qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n",
+ diminput);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (dimfeasible) {
+ if (dimfeasible != *dimension) {
+ fprintf(qh ferr,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
+ dimfeasible, diminput);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ }else
+ qh_setfeasible (*dimension);
+ }else {
+ if (qh CDDinput)
+ *dimension= diminput-1;
+ else
+ *dimension= diminput;
+ *numpoints= numinput;
+ }
+ qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
+ if (qh HALFspace) {
+ qh half_space= coordp= (coordT*) malloc (qh normal_size + sizeof(coordT));
+ if (qh CDDinput) {
+ offsetp= qh half_space;
+ normalp= offsetp + 1;
+ }else {
+ normalp= qh half_space;
+ offsetp= normalp + *dimension;
+ }
+ }
+ qh maxline= diminput * (qh_REALdigits + 5);
+ maximize_(qh maxline, 500);
+ qh line= (char*)malloc ((qh maxline+1) * sizeof (char));
+ *ismalloc= True; /* use malloc since memory not setup */
+ coords= points= qh temp_malloc=
+ (coordT*)malloc((*numpoints)*(*dimension)*sizeof(coordT));
+ if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
+ fprintf(qh ferr, "qhull error: insufficient memory to read %d points\n",
+ numinput);
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ if (isdelaunay && qh ATinfinity) {
+ infinity= points + numinput * (*dimension);
+ for (k= (*dimension) - 1; k--; )
+ infinity[k]= 0.0;
+ }
+ maxcount= numinput * diminput;
+ paraboloid= 0.0;
+ while ((s= (isfirst ? s : fgets(qh line, qh maxline, qh fin)))) {
+ if (!isfirst) {
+ linecount++;
+ if (*s == 'e' || *s == 'E') {
+ if (!memcmp (s, "end", 3) || !memcmp (s, "END", 3)) {
+ if (qh CDDinput )
+ break;
+ else if (wasbegin)
+ fprintf (qh ferr, "qhull input warning: the input appears to be in cdd format. If so, use 'Fd'\n");
+ }
+ }
+ }
+ islong= False;
+ while (*s) {
+ while (isspace(*s))
+ s++;
+ value= qh_strtod (s, &t);
+ if (s == t) {
+ if (!*qh rbox_command)
+ strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+ if (*s && !firsttext)
+ firsttext= linecount;
+ if (!islong && !firstshort && coordcount)
+ firstshort= linecount;
+ break;
+ }
+ if (!firstpoint)
+ firstpoint= linecount;
+ s= t;
+ if (++tokcount > maxcount)
+ continue;
+ if (qh HALFspace) {
+ if (qh CDDinput)
+ *(coordp++)= -value; /* both coefficients and offset */
+ else
+ *(coordp++)= value;
+ }else {
+ *(coords++)= value;
+ if (qh CDDinput && !coordcount) {
+ if (value != 1.0) {
+ fprintf (qh ferr, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
+ linecount);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ coords--;
+ }else if (isdelaunay) {
+ paraboloid += value * value;
+ if (qh ATinfinity) {
+ if (qh CDDinput)
+ infinity[coordcount-1] += value;
+ else
+ infinity[coordcount] += value;
+ }
+ }
+ }
+ if (++coordcount == diminput) {
+ coordcount= 0;
+ if (isdelaunay) {
+ *(coords++)= paraboloid;
+ maximize_(maxboloid, paraboloid);
+ paraboloid= 0.0;
+ }else if (qh HALFspace) {
+ if (!qh_sethalfspace (*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
+ fprintf (qh ferr, "The halfspace was on line %d\n", linecount);
+ if (wasbegin)
+ fprintf (qh ferr, "The input appears to be in cdd format. If so, you should use option 'Fd'\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ coordp= qh half_space;
+ }
+ while (isspace(*s))
+ s++;
+ if (*s) {
+ islong= True;
+ if (!firstlong)
+ firstlong= linecount;
+ }
+ }
+ }
+ if (!islong && !firstshort && coordcount)
+ firstshort= linecount;
+ if (!isfirst && s - qh line >= qh maxline) {
+ fprintf(qh ferr, "qhull input error: line %d contained more than %d characters\n",
+ linecount, (int) (s - qh line));
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ isfirst= False;
+ }
+ if (tokcount != maxcount) {
+ newnum= fmin_(numinput, tokcount/diminput);
+ fprintf(qh ferr,"\
+qhull warning: instead of %d %d-dimensional points, input contains\n\
+%d points and %d extra coordinates. Line %d is the first\npoint",
+ numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
+ if (firsttext)
+ fprintf(qh ferr, ", line %d is the first comment", firsttext);
+ if (firstshort)
+ fprintf(qh ferr, ", line %d is the first short\nline", firstshort);
+ if (firstlong)
+ fprintf(qh ferr, ", line %d is the first long line", firstlong);
+ fprintf(qh ferr, ". Continue with %d points.\n", newnum);
+ numinput= newnum;
+ if (isdelaunay && qh ATinfinity) {
+ for (k= tokcount % diminput; k--; )
+ infinity[k] -= *(--coords);
+ *numpoints= newnum+1;
+ }else {
+ coords -= tokcount % diminput;
+ *numpoints= newnum;
+ }
+ }
+ if (isdelaunay && qh ATinfinity) {
+ for (k= (*dimension) -1; k--; )
+ infinity[k] /= numinput;
+ if (coords == infinity)
+ coords += (*dimension) -1;
+ else {
+ for (k= 0; k < (*dimension) -1; k++)
+ *(coords++)= infinity[k];
+ }
+ *(coords++)= maxboloid * 1.1;
+ }
+ if (qh rbox_command[0]) {
+ qh rbox_command[strlen(qh rbox_command)-1]= '\0';
+ if (!strcmp (qh rbox_command, "./rbox D4"))
+ fprintf (qh ferr, "\n\
+This is the qhull test case. If any errors or core dumps occur,\n\
+recompile qhull with 'make new'. If errors still occur, there is\n\
+an incompatibility. You should try a different compiler. You can also\n\
+change the choices in user.h. If you discover the source of the problem,\n\
+please send mail to qhull_bug@geom.umn.edu.\n\
+\n\
+Type 'qhull' for a short list of options.\n");
+ }
+ free (qh line);
+ qh line= NULL;
+ if (qh half_space) {
+ free (qh half_space);
+ qh half_space= NULL;
+ }
+ qh temp_malloc= NULL;
+ trace1((qh ferr,"qh_readpoints: read in %d %d-dimensional points\n",
+ numinput, diminput));
+ return(points);
+} /* readpoints */
+
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="setfeasible">-</a>
+
+ qh_setfeasible( dim )
+ set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
+
+ notes:
+ "n,n,n" already checked by qh_initflags()
+ see qh_readfeasible()
+*/
+void qh_setfeasible (int dim) {
+ int tokcount= 0;
+ char *s;
+ coordT *coords, value;
+
+ if (!(s= qh feasible_string)) {
+ fprintf(qh ferr, "\
+qhull input error: halfspace intersection needs a feasible point.\n\
+Either prepend the input with 1 point or use 'Hn,n,n'. See manual.\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (!(qh feasible_point= (pointT*)malloc (dim* sizeof(coordT)))) {
+ fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
+ qh_errexit(qh_ERRmem, NULL, NULL);
+ }
+ coords= qh feasible_point;
+ while (*s) {
+ value= qh_strtod (s, &s);
+ if (++tokcount > dim) {
+ fprintf (qh ferr, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
+ qh feasible_string, dim);
+ break;
+ }
+ *(coords++)= value;
+ if (*s)
+ s++;
+ }
+ while (++tokcount <= dim)
+ *(coords++)= 0.0;
+} /* setfeasible */
+
+/*-<a href="qh-io.htm#TOC"
+ >-------------------------------</a><a name="skipfacet">-</a>
+
+ qh_skipfacet( facet )
+ returns 'True' if this facet is not to be printed
+
+ notes:
+ based on the user provided slice thresholds and 'good' specifications
+*/
+boolT qh_skipfacet(facetT *facet) {
+ facetT *neighbor, **neighborp;
+
+ if (qh PRINTneighbors) {
+ if (facet->good)
+ return !qh PRINTgood;
+ FOREACHneighbor_(facet) {
+ if (neighbor->good)
+ return False;
+ }
+ return True;
+ }else if (qh PRINTgood)
+ return !facet->good;
+ else if (!facet->normal)
+ return True;
+ return (!qh_inthresholds (facet->normal, NULL));
+} /* skipfacet */
+
diff --git a/extern/qhull/src/io.h b/extern/qhull/src/io.h
new file mode 100644
index 00000000000..351d56b3708
--- /dev/null
+++ b/extern/qhull/src/io.h
@@ -0,0 +1,149 @@
+/*<html><pre> -<a href="qh-io.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ io.h
+ declarations of Input/Output functions
+
+ see README, qhull.h and io.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+/*============ constants and flags ==================*/
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_MAXfirst">-</a>
+
+ qh_MAXfirst
+ maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst 200
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_MINradius">-</a>
+
+ qh_MINradius
+ min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_GEOMepsilon">-</a>
+
+ qh_GEOMepsilon
+ adjust outer planes for 'lines closer' and geomview roundoff.
+ This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="qh_WHITESPACE">-</a>
+
+ qh_WHITESPACE
+ possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="RIDGE">-</a>
+
+ qh_RIDGE
+ to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+ qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*-<a href="qh-io.htm#TOC"
+ >--------------------------------</a><a name="printvridgeT">-</a>
+
+ printvridgeT
+ prints results of qh_printvdiagram
+
+ see:
+ <a href="io.c#printvridge">qh_printvridge</a> for an example
+*/
+typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+void dfacet( unsigned id);
+void dvertex( unsigned id);
+void qh_countfacets (facetT *facetlist, setT *facets, boolT printall,
+ int *numfacetsp, int *numsimplicialp, int *totneighborsp,
+ int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT *qh_detvridge (vertexT *vertex);
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
+int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
+void qh_markkeep (facetT *facetlist);
+setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
+void qh_order_vertexneighbors(vertexT *vertex);
+void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
+void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
+void qh_printcentrum (FILE *fp, facetT *facet, realT radius);
+void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
+void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printfacet(FILE *fp, facetT *facet);
+void qh_printfacet2math(FILE *fp, facetT *facet, int notfirst);
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+ facetT *facet, realT offset, realT color[3]);
+void qh_printfacet3math (FILE *fp, facetT *facet, int notfirst);
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
+void qh_printfacetheader(FILE *fp, facetT *facet);
+void qh_printfacetridges(FILE *fp, facetT *facet);
+void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printhelp_degenerate(FILE *fp);
+void qh_printhelp_singular(FILE *fp);
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+ setT *vertices, realT color[3]);
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void qh_printpoint(FILE *fp, char *string, pointT *point);
+void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
+void qh_printpoint3 (FILE *fp, pointT *point);
+void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void qh_printridge(FILE *fp, ridgeT *ridge);
+void qh_printspheres(FILE *fp, setT *vertices, realT radius);
+void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void qh_printvertex(FILE *fp, vertexT *vertex);
+void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
+ setT *facets, boolT printall);
+void qh_printvertices (FILE *fp, char* string, setT *vertices);
+void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void qh_produce_output(void);
+void qh_projectdim3 (pointT *source, pointT *destination);
+int qh_readfeasible (int dim, char *remainder);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+void qh_setfeasible (int dim);
+boolT qh_skipfacet(facetT *facet);
+
+#endif /* qhDEFio */
diff --git a/extern/qhull/src/mem.c b/extern/qhull/src/mem.c
new file mode 100644
index 00000000000..72934626684
--- /dev/null
+++ b/extern/qhull/src/mem.c
@@ -0,0 +1,447 @@
+/*<html><pre> -<a href="qh-mem.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ mem.c
+ memory management routines for qhull
+
+ This is a standalone program.
+
+ To initialize memory:
+
+ qh_meminit (stderr);
+ qh_meminitbuffers (qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
+ qh_memsize(sizeof(facetT));
+ qh_memsize(sizeof(facetT));
+ ...
+ qh_memsetup();
+
+ To free up all memory buffers:
+ qh_memfreeshort (&curlong, &totlong);
+
+ if qh_NOmem,
+ malloc/free is used instead of mem.c
+
+ notes:
+ uses Quickfit algorithm (freelists for commonly allocated sizes)
+ assumes small sizes for freelists (it discards the tail of memory buffers)
+
+ see:
+ qh-mem.htm and mem.h
+ global.c (qh_initbuffers) for an example of using mem.c
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mem.h"
+
+#ifndef qhDEFqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void qh_errexit(int exitcode, facetT *, ridgeT *);
+#endif
+
+/*============ -global data structure ==============
+ see mem.h for definition
+*/
+
+qhmemT qhmem= {0}; /* remove "= {0}" if this causes a compiler error */
+
+#ifndef qh_NOmem
+
+/*============= internal functions ==============*/
+
+static int qh_intcompare(const void *i, const void *j);
+
+/*========== functions in alphabetical order ======== */
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="intcompare">-</a>
+
+ qh_intcompare( i, j )
+ used by qsort and bsearch to compare two integers
+*/
+static int qh_intcompare(const void *i, const void *j) {
+ return(*((int *)i) - *((int *)j));
+} /* intcompare */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memalloc">-</a>
+
+ qh_memalloc( insize )
+ returns object of insize bytes
+ qhmem is the global memory structure
+
+ returns:
+ pointer to allocated memory
+ errors if insufficient memory
+
+ notes:
+ use explicit type conversion to avoid type warnings on some compilers
+ actual object may be larger than insize
+ use qh_memalloc_() for inline code for quick allocations
+ logs allocations if 'T5'
+
+ design:
+ if size < qhmem.LASTsize
+ if qhmem.freelists[size] non-empty
+ return first object on freelist
+ else
+ round up request to size of qhmem.freelists[size]
+ allocate new allocation buffer if necessary
+ allocate object from allocation buffer
+ else
+ allocate object with malloc()
+*/
+void *qh_memalloc(int insize) {
+ void **freelistp, *newbuffer;
+ int index, size;
+ int outsize, bufsize;
+ void *object;
+
+ if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
+ index= qhmem.indextable[insize];
+ freelistp= qhmem.freelists+index;
+ if ((object= *freelistp)) {
+ qhmem.cntquick++;
+ *freelistp= *((void **)*freelistp); /* replace freelist with next object */
+ return (object);
+ }else {
+ outsize= qhmem.sizetable[index];
+ qhmem.cntshort++;
+ if (outsize > qhmem .freesize) {
+ if (!qhmem.curbuffer)
+ bufsize= qhmem.BUFinit;
+ else
+ bufsize= qhmem.BUFsize;
+ qhmem.totshort += bufsize;
+ if (!(newbuffer= malloc(bufsize))) {
+ fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+ qh_errexit(qhmem_ERRmem, NULL, NULL);
+ }
+ *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer
+ list */
+ qhmem.curbuffer= newbuffer;
+ size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+ qhmem.freemem= (void *)((char *)newbuffer+size);
+ qhmem.freesize= bufsize - size;
+ }
+ object= qhmem.freemem;
+ qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
+ qhmem.freesize -= outsize;
+ return object;
+ }
+ }else { /* long allocation */
+ if (!qhmem.indextable) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
+ qh_errexit(qhmem_ERRqhull, NULL, NULL);
+ }
+ outsize= insize;
+ qhmem .cntlong++;
+ qhmem .curlong++;
+ qhmem .totlong += outsize;
+ if (qhmem.maxlong < qhmem.totlong)
+ qhmem.maxlong= qhmem.totlong;
+ if (!(object= malloc(outsize))) {
+ fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+ qh_errexit(qhmem_ERRmem, NULL, NULL);
+ }
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
+ }
+ return (object);
+} /* memalloc */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memfree">-</a>
+
+ qh_memfree( object, size )
+ free up an object of size bytes
+ size is insize from qh_memalloc
+
+ notes:
+ object may be NULL
+ type checking warns if using (void **)object
+ use qh_memfree_() for quick free's of small objects
+
+ design:
+ if size <= qhmem.LASTsize
+ append object to corresponding freelist
+ else
+ call free(object)
+*/
+void qh_memfree(void *object, int size) {
+ void **freelistp;
+
+ if (!object)
+ return;
+ if (size <= qhmem.LASTsize) {
+ qhmem .freeshort++;
+ freelistp= qhmem.freelists + qhmem.indextable[size];
+ *((void **)object)= *freelistp;
+ *freelistp= object;
+ }else {
+ qhmem .freelong++;
+ qhmem .totlong -= size;
+ free (object);
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
+ }
+} /* memfree */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="memfreeshort">-</a>
+
+ qh_memfreeshort( curlong, totlong )
+ frees up all short and qhmem memory allocations
+
+ returns:
+ number and size of current long allocations
+*/
+void qh_memfreeshort (int *curlong, int *totlong) {
+ void *buffer, *nextbuffer;
+
+ *curlong= qhmem .cntlong - qhmem .freelong;
+ *totlong= qhmem .totlong;
+ for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
+ nextbuffer= *((void **) buffer);
+ free(buffer);
+ }
+ qhmem.curbuffer= NULL;
+ if (qhmem .LASTsize) {
+ free (qhmem .indextable);
+ free (qhmem .freelists);
+ free (qhmem .sizetable);
+ }
+ memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
+} /* memfreeshort */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="meminit">-</a>
+
+ qh_meminit( ferr )
+ initialize qhmem and test sizeof( void*)
+*/
+void qh_meminit (FILE *ferr) {
+
+ memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
+ qhmem.ferr= ferr;
+ if (sizeof(void*) < sizeof(int)) {
+ fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int). qset.c will not work\n");
+ exit (1); /* can not use qh_errexit() */
+ }
+} /* meminit */
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="meminitbuffers">-</a>
+
+ qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
+ initialize qhmem
+ if tracelevel >= 5, trace memory allocations
+ alignment= desired address alignment for memory allocations
+ numsizes= number of freelists
+ bufsize= size of additional memory buffers for short allocations
+ bufinit= size of initial memory buffer for short allocations
+*/
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+ qhmem.IStracing= tracelevel;
+ qhmem.NUMsizes= numsizes;
+ qhmem.BUFsize= bufsize;
+ qhmem.BUFinit= bufinit;
+ qhmem.ALIGNmask= alignment-1;
+ if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
+ qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
+ if (!qhmem.sizetable || !qhmem.freelists) {
+ fprintf(qhmem.ferr, "qhull error (qh_meminit): insufficient memory\n");
+ qh_errexit (qhmem_ERRmem, NULL, NULL);
+ }
+ if (qhmem.IStracing >= 1)
+ fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
+} /* meminitbuffers */
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="memsetup">-</a>
+
+ qh_memsetup()
+ set up memory after running memsize()
+*/
+void qh_memsetup (void) {
+ int k,i;
+
+ qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
+ qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
+ if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
+ fprintf (qhmem.ferr, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
+ qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
+ qh_errexit(qhmem_ERRmem, NULL, NULL);
+ }
+ if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) {
+ fprintf(qhmem.ferr, "qhull error (qh_memsetup): insufficient memory\n");
+ qh_errexit(qhmem_ERRmem, NULL, NULL);
+ }
+ for(k=qhmem.LASTsize+1; k--; )
+ qhmem.indextable[k]= k;
+ i= 0;
+ for(k= 0; k <= qhmem.LASTsize; k++) {
+ if (qhmem.indextable[k] <= qhmem.sizetable[i])
+ qhmem.indextable[k]= i;
+ else
+ qhmem.indextable[k]= ++i;
+ }
+} /* memsetup */
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="memsize">-</a>
+
+ qh_memsize( size )
+ define a free list for this size
+*/
+void qh_memsize(int size) {
+ int k;
+
+ if (qhmem .LASTsize) {
+ fprintf (qhmem .ferr, "qhull error (qh_memsize): called after qhmem_setup\n");
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+ for(k= qhmem.TABLEsize; k--; ) {
+ if (qhmem.sizetable[k] == size)
+ return;
+ }
+ if (qhmem.TABLEsize < qhmem.NUMsizes)
+ qhmem.sizetable[qhmem.TABLEsize++]= size;
+ else
+ fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
+} /* memsize */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="memstatistics">-</a>
+
+ qh_memstatistics( fp )
+ print out memory statistics
+
+ notes:
+ does not account for wasted memory at the end of each block
+*/
+void qh_memstatistics (FILE *fp) {
+ int i, count, totfree= 0;
+ void *object;
+
+ for (i=0; i < qhmem.TABLEsize; i++) {
+ count=0;
+ for (object= qhmem .freelists[i]; object; object= *((void **)object))
+ count++;
+ totfree += qhmem.sizetable[i] * count;
+ }
+ fprintf (fp, "\nmemory statistics:\n\
+%7d quick allocations\n\
+%7d short allocations\n\
+%7d long allocations\n\
+%7d short frees\n\
+%7d long frees\n\
+%7d bytes of short memory in use\n\
+%7d bytes of short memory in freelists\n\
+%7d bytes of long memory allocated (except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n\
+%7d bytes per memory buffer (initially %d bytes)\n",
+ qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
+ qhmem .freeshort, qhmem.freelong,
+ qhmem .totshort - qhmem .freesize - totfree,
+ totfree,
+ qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
+ qhmem .BUFsize, qhmem .BUFinit);
+ if (qhmem.cntlarger) {
+ fprintf (fp, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
+ qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
+ fprintf (fp, " freelists (bytes->count):");
+ }
+ for (i=0; i < qhmem.TABLEsize; i++) {
+ count=0;
+ for (object= qhmem .freelists[i]; object; object= *((void **)object))
+ count++;
+ fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
+ }
+ fprintf (fp, "\n\n");
+} /* memstatistics */
+
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="NOmem">-</a>
+
+ qh_NOmem
+ turn off quick-fit memory allocation
+
+ notes:
+ uses malloc() and free() instead
+*/
+#else /* qh_NOmem */
+
+void *qh_memalloc(int insize) {
+ void *object;
+
+ if (!(object= malloc(insize))) {
+ fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+ qh_errexit(qhmem_ERRmem, NULL, NULL);
+ }
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", insize, object);
+ return object;
+}
+
+void qh_memfree(void *object, int size) {
+
+ if (!object)
+ return;
+ free (object);
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
+}
+
+void qh_memfreeshort (int *curlong, int *totlong) {
+
+ memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
+ *curlong= 0;
+ *totlong= 0;
+}
+
+void qh_meminit (FILE *ferr) {
+
+ memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
+ qhmem.ferr= ferr;
+ if (sizeof(void*) < sizeof(int)) {
+ fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int). qset.c will not work\n");
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+}
+
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+ qhmem.IStracing= tracelevel;
+
+}
+
+void qh_memsetup (void) {
+
+}
+
+void qh_memsize(int size) {
+
+}
+
+void qh_memstatistics (FILE *fp) {
+
+}
+
+#endif /* qh_NOmem */
diff --git a/extern/qhull/src/mem.h b/extern/qhull/src/mem.h
new file mode 100644
index 00000000000..e9ebd1bb9bc
--- /dev/null
+++ b/extern/qhull/src/mem.h
@@ -0,0 +1,174 @@
+/*<html><pre> -<a href="qh-mem.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ mem.h
+ prototypes for memory management functions
+
+ see qh-mem.htm, mem.c and qset.h
+
+ for error handling, writes message and calls
+ qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
+ and
+ qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem
+
+/*-<a href="qh-mem.htm#TOC"
+ >-------------------------------</a><a name="NOmem">-</a>
+
+ qh_NOmem
+ turn off quick-fit memory allocation
+
+ notes:
+ mem.c implements Quickfit memory allocation for about 20% time
+ savings. If it fails on your machine, try to locate the
+ problem, and send the answer to qhull@geom.umn.edu. If this can
+ not be done, define qh_NOmem to use malloc/free instead.
+
+ #define qh_NOmem
+*/
+
+/*-------------------------------------------
+ to avoid bus errors, memory allocation must consider alignment requirements.
+ malloc() automatically takes care of alignment. Since mem.c manages
+ its own memory, we need to explicitly specify alignment in
+ qh_meminitbuffers().
+
+ A safe choice is sizeof(double). sizeof(float) may be used if doubles
+ do not occur in data structures and pointers are the same size. Be careful
+ of machines (e.g., DEC Alpha) with large pointers. If gcc is available,
+ use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+ see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4 /* matches qh_ERRmem in qhull.h */
+#define qhmem_ERRqhull 5 /* matches qh_ERRqhull in qhull.h */
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="ptr_intT">-</a>
+
+ ptr_intT
+ for casting a void* to an integer-type
+
+ notes:
+ On 64-bit machines, a pointer may be larger than an 'int'.
+ qh_meminit() checks that 'long' holds a 'void*'
+*/
+typedef unsigned long ptr_intT;
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="qhmemT">-</a>
+
+ qhmemT
+ global memory structure for mem.c
+
+ notes:
+ users should ignore qhmem except for writing extensions
+ qhmem is allocated in mem.c
+
+ qhmem could be swapable like qh and qhstat, but then
+ multiple qh's and qhmem's would need to keep in synch.
+ A swapable qhmem would also waste memory buffers. As long
+ as memory operations are atomic, there is no problem with
+ multiple qh structures being active at the same time.
+ If you need separate address spaces, you can swap the
+ contents of qhmem.
+*/
+typedef struct qhmemT qhmemT;
+extern qhmemT qhmem;
+
+struct qhmemT { /* global memory management variables */
+ int BUFsize; /* size of memory allocation buffer */
+ int BUFinit; /* initial size of memory allocation buffer */
+ int TABLEsize; /* actual number of sizes in free list table */
+ int NUMsizes; /* maximum number of sizes in free list table */
+ int LASTsize; /* last size in free list table */
+ int ALIGNmask; /* worst-case alignment, must be 2^n-1 */
+ void **freelists; /* free list table, linked by offset 0 */
+ int *sizetable; /* size of each freelist */
+ int *indextable; /* size->index table */
+ void *curbuffer; /* current buffer, linked by offset 0 */
+ void *freemem; /* free memory in curbuffer */
+ int freesize; /* size of free memory in bytes */
+ void *tempstack; /* stack of temporary memory, managed by users */
+ FILE *ferr; /* file for reporting errors */
+ int IStracing; /* =5 if tracing memory allocations */
+ int cntquick; /* count of quick allocations */
+ /* remove statistics doesn't effect speed */
+ int cntshort; /* count of short allocations */
+ int cntlong; /* count of long allocations */
+ int curlong; /* current count of inuse, long allocations */
+ int freeshort; /* count of short memfrees */
+ int freelong; /* count of long memfrees */
+ int totshort; /* total size of short allocations */
+ int totlong; /* total size of long allocations */
+ int maxlong; /* maximum totlong */
+ int cntlarger; /* count of setlarger's */
+ int totlarger; /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memalloc_">-</a>
+
+ qh_memalloc_(size, object, type)
+ returns object of size bytes
+ assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#ifdef qh_NOmem
+#define qh_memalloc_(size, freelistp, object, type) {\
+ object= (type*)qh_memalloc (size); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(size, freelistp, object, type) {\
+ freelistp= qhmem.freelists + qhmem.indextable[size];\
+ if ((object= (type*)*freelistp)) {\
+ qhmem.cntquick++; \
+ *freelistp= *((void **)*freelistp);\
+ }else object= (type*)qh_memalloc (size);}
+#endif
+
+/*-<a href="qh-mem.htm#TOC"
+ >--------------------------------</a><a name="memfree_">-</a>
+
+ qh_memfree_(object, size)
+ free up an object
+
+ notes:
+ object may be NULL
+ assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+#ifdef qh_NOmem
+#define qh_memfree_(object, size, freelistp) {\
+ qh_memfree (object, size); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(object, size, freelistp) {\
+ if (object) { \
+ qhmem .freeshort++;\
+ freelistp= qhmem.freelists + qhmem.indextable[size];\
+ *((void **)object)= *freelistp;\
+ *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+void *qh_memalloc(int insize);
+void qh_memfree (void *object, int size);
+void qh_memfreeshort (int *curlong, int *totlong);
+void qh_meminit (FILE *ferr);
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
+ int bufsize, int bufinit);
+void qh_memsetup (void);
+void qh_memsize(int size);
+void qh_memstatistics (FILE *fp);
+
+#endif /* qhDEFmem */
diff --git a/extern/qhull/src/merge.c b/extern/qhull/src/merge.c
new file mode 100644
index 00000000000..34ecda1865f
--- /dev/null
+++ b/extern/qhull/src/merge.c
@@ -0,0 +1,3626 @@
+/*<html><pre> -<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ merge.c
+ merges non-convex facets
+
+ see qh-merge.htm and merge.h
+
+ other modules call qh_premerge() and qh_postmerge()
+
+ the user may call qh_postmerge() to perform additional merges.
+
+ To remove deleted facets and vertices (qhull() in qhull.c):
+ qh_partitionvisible (!qh_ALL, &numoutside); // visible_list, newfacet_list
+ qh_deletevisible (); // qh.visible_list
+ qh_resetlists (False, qh_RESETvisible); // qh.visible_list newvertex_list newfacet_list
+
+ assumes qh.CENTERtype= centrum
+
+ merges occur in qh_mergefacet and in qh_mergecycle
+ vertex->neighbors not set until the first merge occurs
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+#ifndef qh_NOmerge
+
+/*=========== internal prototypes =========*/
+
+static int qh_compareangle(const void *p1, const void *p2);
+static int qh_comparemerge(const void *p1, const void *p2);
+static int qh_comparevisit (const void *p1, const void *p2);
+
+
+/*===== functions (alphabetical after premerge and postmerge) ======*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="premerge">-</a>
+
+ qh_premerge( apex, maxcentrum )
+ pre-merge nonconvex facets in qh.newfacet_list for apex
+ maxcentrum defines coplanar and concave (qh_test_appendmerge)
+
+ returns:
+ deleted facets added to qh.visible_list with facet->visible set
+
+ notes:
+ uses globals, qh.MERGEexact, qh.PREmerge
+
+ design:
+ mark duplicate ridges in qh.newfacet_list
+ merge facet cycles in qh.newfacet_list
+ merge duplicate ridges and concave facets in qh.newfacet_list
+ check merged facet cycles for degenerate and redundant facets
+ merge degenerate and redundant facets
+ collect coplanar and concave facets
+ merge concave, coplanar, degenerate, and redundant facets
+*/
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
+ boolT othermerge= False;
+ facetT *newfacet;
+
+ if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
+ return;
+ trace2((qh ferr, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
+ maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
+ if (qh IStracing >= 4 && qh num_facets < 50)
+ qh_printlists();
+ qh centrum_radius= maxcentrum;
+ qh cos_max= maxangle;
+ qh degen_mergeset= qh_settemp (qh TEMPsize);
+ qh facet_mergeset= qh_settemp (qh TEMPsize);
+ if (qh hull_dim >=3) {
+ qh_mark_dupridges (qh newfacet_list); /* facet_mergeset */
+ qh_mergecycle_all (qh newfacet_list, &othermerge);
+ qh_forcedmerges (&othermerge /* qh facet_mergeset */);
+ FORALLnew_facets { /* test samecycle merges */
+ if (!newfacet->simplicial && !newfacet->mergeridge)
+ qh_degen_redundant_neighbors (newfacet, NULL);
+ }
+ if (qh_merge_degenredundant())
+ othermerge= True;
+ }else /* qh hull_dim == 2 */
+ qh_mergecycle_all (qh newfacet_list, &othermerge);
+ qh_flippedmerges (qh newfacet_list, &othermerge);
+ if (!qh MERGEexact || zzval_(Ztotmerge)) {
+ zinc_(Zpremergetot);
+ qh POSTmerging= False;
+ qh_getmergeset_initial (qh newfacet_list);
+ qh_all_merges (othermerge, False);
+ }
+ qh_settempfree(&qh facet_mergeset);
+ qh_settempfree(&qh degen_mergeset);
+} /* premerge */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="postmerge">-</a>
+
+ qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
+ post-merge nonconvex facets as defined by maxcentrum and maxangle
+ 'reason' is for reporting progress
+ if vneighbors,
+ calls qh_test_vneighbors at end of qh_all_merge
+ if firstmerge,
+ calls qh_reducevertices before qh_getmergeset
+
+ returns:
+ if first call (qh.visible_list != qh.facet_list),
+ builds qh.facet_newlist, qh.newvertex_list
+ deleted facets added to qh.visible_list with facet->visible
+ qh.visible_list == qh.facet_list
+
+ notes:
+
+
+ design:
+ if first call
+ set qh.visible_list and qh.newfacet_list to qh.facet_list
+ add all facets to qh.newfacet_list
+ mark non-simplicial facets, facet->newmerge
+ set qh.newvertext_list to qh.vertex_list
+ add all vertices to qh.newvertex_list
+ if a pre-merge occured
+ set vertex->delridge {will retest the ridge}
+ if qh.MERGEexact
+ call qh_reducevertices()
+ if no pre-merging
+ merge flipped facets
+ determine non-convex facets
+ merge all non-convex facets
+*/
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle,
+ boolT vneighbors) {
+ facetT *newfacet;
+ boolT othermerges= False;
+ vertexT *vertex;
+
+ if (qh REPORTfreq || qh IStracing) {
+ qh_buildtracing (NULL, NULL);
+ qh_printsummary (qh ferr);
+ if (qh PRINTstatistics)
+ qh_printallstatistics (qh ferr, "reason");
+ fprintf (qh ferr, "\n%s with 'C%.2g' and 'A%.2g'\n",
+ reason, maxcentrum, maxangle);
+ }
+ trace2((qh ferr, "qh_postmerge: postmerge. test vneighbors? %d\n",
+ vneighbors));
+ qh centrum_radius= maxcentrum;
+ qh cos_max= maxangle;
+ qh POSTmerging= True;
+ qh degen_mergeset= qh_settemp (qh TEMPsize);
+ qh facet_mergeset= qh_settemp (qh TEMPsize);
+ if (qh visible_list != qh facet_list) { /* first call */
+ qh NEWfacets= True;
+ qh visible_list= qh newfacet_list= qh facet_list;
+ FORALLnew_facets {
+ newfacet->newfacet= True;
+ if (!newfacet->simplicial)
+ newfacet->newmerge= True;
+ zinc_(Zpostfacets);
+ }
+ qh newvertex_list= qh vertex_list;
+ FORALLvertices
+ vertex->newlist= True;
+ if (qh VERTEXneighbors) { /* a merge has occurred */
+ FORALLvertices
+ vertex->delridge= True; /* test for redundant, needed? */
+ if (qh MERGEexact) {
+ if (qh hull_dim <= qh_DIMreduceBuild)
+ qh_reducevertices(); /* was skipped during pre-merging */
+ }
+ }
+ if (!qh PREmerge && !qh MERGEexact)
+ qh_flippedmerges (qh newfacet_list, &othermerges);
+ }
+ qh_getmergeset_initial (qh newfacet_list);
+ qh_all_merges (False, vneighbors);
+ qh_settempfree(&qh facet_mergeset);
+ qh_settempfree(&qh degen_mergeset);
+} /* post_merge */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="all_merges">-</a>
+
+ qh_all_merges( othermerge, vneighbors )
+ merge all non-convex facets
+
+ set othermerge if already merged facets (for qh_reducevertices)
+ if vneighbors
+ tests vertex neighbors for convexity at end
+ qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
+ qh.degen_mergeset is defined
+ if qh.MERGEexact && !qh.POSTmerging,
+ does not merge coplanar facets
+
+ returns:
+ deleted facets added to qh.visible_list with facet->visible
+ deleted vertices added qh.delvertex_list with vertex->delvertex
+
+ notes:
+ unless !qh.MERGEindependent,
+ merges facets in independent sets
+ uses qh.newfacet_list as argument since merges call qh_removefacet()
+
+ design:
+ while merges occur
+ for each merge in qh.facet_mergeset
+ unless one of the facets was already merged in this pass
+ merge the facets
+ test merged facets for additional merges
+ add merges to qh.facet_mergeset
+ if vertices record neighboring facets
+ rename redundant vertices
+ update qh.facet_mergeset
+ if vneighbors ??
+ tests vertex neighbors for convexity at end
+*/
+void qh_all_merges (boolT othermerge, boolT vneighbors) {
+ facetT *facet1, *facet2;
+ mergeT *merge;
+ boolT wasmerge= True, isreduce;
+ void **freelistp; /* used !qh_NOmem */
+ vertexT *vertex;
+ mergeType mergetype;
+ int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
+
+ trace2((qh ferr, "qh_all_merges: starting to merge facets beginning from f%d\n",
+ getid_(qh newfacet_list)));
+ while (True) {
+ wasmerge= False;
+ while (qh_setsize (qh facet_mergeset)) {
+ while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
+ facet1= merge->facet1;
+ facet2= merge->facet2;
+ mergetype= merge->type;
+ qh_memfree_(merge, sizeof(mergeT), freelistp);
+ if (facet1->visible || facet2->visible) /*deleted facet*/
+ continue;
+ if ((facet1->newfacet && !facet1->tested)
+ || (facet2->newfacet && !facet2->tested)) {
+ if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
+ continue; /* perform independent sets of merges */
+ }
+ qh_merge_nonconvex (facet1, facet2, mergetype);
+ numdegenredun += qh_merge_degenredundant();
+ numnewmerges++;
+ wasmerge= True;
+ if (mergetype == MRGconcave)
+ numconcave++;
+ else /* MRGcoplanar or MRGanglecoplanar */
+ numcoplanar++;
+ } /* while setdellast */
+ if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild
+ && numnewmerges > qh_MAXnewmerges) {
+ numnewmerges= 0;
+ qh_reducevertices(); /* otherwise large post merges too slow */
+ }
+ qh_getmergeset (qh newfacet_list); /* facet_mergeset */
+ } /* while mergeset */
+ if (qh VERTEXneighbors) {
+ isreduce= False;
+ if (qh hull_dim >=4 && qh POSTmerging) {
+ FORALLvertices
+ vertex->delridge= True;
+ isreduce= True;
+ }
+ if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging)
+ && qh hull_dim <= qh_DIMreduceBuild) {
+ othermerge= False;
+ isreduce= True;
+ }
+ if (isreduce) {
+ if (qh_reducevertices()) {
+ qh_getmergeset (qh newfacet_list); /* facet_mergeset */
+ continue;
+ }
+ }
+ }
+ if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */))
+ continue;
+ break;
+ } /* while (True) */
+ if (qh CHECKfrequently && !qh MERGEexact) {
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault);
+ /* qh_checkconnect (); [this is slow and it changes the facet order] */
+ qh RANDOMdist= qh old_randomdist;
+ }
+ trace1((qh ferr, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
+ numcoplanar, numconcave, numdegenredun));
+ if (qh IStracing >= 4 && qh num_facets < 50)
+ qh_printlists ();
+} /* all_merges */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="appendmergeset">-</a>
+
+ qh_appendmergeset( facet, neighbor, mergetype, angle )
+ appends an entry to qh.facet_mergeset or qh.degen_mergeset
+
+ angle ignored if NULL or !qh.ANGLEmerge
+
+ returns:
+ merge appended to facet_mergeset or degen_mergeset
+ sets ->degenerate or ->redundant if degen_mergeset
+
+ see:
+ qh_test_appendmerge()
+
+ design:
+ allocate merge entry
+ if regular merge
+ append to qh.facet_mergeset
+ else if degenerate merge and qh.facet_mergeset is all degenerate
+ append to qh.degen_mergeset
+ else if degenerate merge
+ prepend to qh.degen_mergeset
+ else if redundant merge
+ append to qh.degen_mergeset
+*/
+void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
+ mergeT *merge, *lastmerge;
+ void **freelistp; /* used !qh_NOmem */
+
+ if (facet->redundant)
+ return;
+ if (facet->degenerate && mergetype == MRGdegen)
+ return;
+ qh_memalloc_(sizeof(mergeT), freelistp, merge, mergeT);
+ merge->facet1= facet;
+ merge->facet2= neighbor;
+ merge->type= mergetype;
+ if (angle && qh ANGLEmerge)
+ merge->angle= *angle;
+ if (mergetype < MRGdegen)
+ qh_setappend (&(qh facet_mergeset), merge);
+ else if (mergetype == MRGdegen) {
+ facet->degenerate= True;
+ if (!(lastmerge= (mergeT*)qh_setlast (qh degen_mergeset))
+ || lastmerge->type == MRGdegen)
+ qh_setappend (&(qh degen_mergeset), merge);
+ else
+ qh_setaddnth (&(qh degen_mergeset), 0, merge);
+ }else if (mergetype == MRGredundant) {
+ facet->redundant= True;
+ qh_setappend (&(qh degen_mergeset), merge);
+ }else /* mergetype == MRGmirror */ {
+ if (facet->redundant || neighbor->redundant) {
+ fprintf(qh ferr, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
+ facet->id, neighbor->id);
+ qh_errexit2 (qh_ERRqhull, facet, neighbor);
+ }
+ if (!qh_setequal (facet->vertices, neighbor->vertices)) {
+ fprintf(qh ferr, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
+ facet->id, neighbor->id);
+ qh_errexit2 (qh_ERRqhull, facet, neighbor);
+ }
+ facet->redundant= True;
+ neighbor->redundant= True;
+ qh_setappend (&(qh degen_mergeset), merge);
+ }
+} /* appendmergeset */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="basevertices">-</a>
+
+ qh_basevertices( samecycle )
+ return temporary set of base vertices for samecycle
+ samecycle is first facet in the cycle
+ assumes apex is SETfirst_( samecycle->vertices )
+
+ returns:
+ vertices (settemp)
+ all ->seen are cleared
+
+ notes:
+ uses qh_vertex_visit;
+
+ design:
+ for each facet in samecycle
+ for each unseen vertex in facet->vertices
+ append to result
+*/
+setT *qh_basevertices (facetT *samecycle) {
+ facetT *same;
+ vertexT *apex, *vertex, **vertexp;
+ setT *vertices= qh_settemp (qh TEMPsize);
+
+ apex= SETfirstt_(samecycle->vertices, vertexT);
+ apex->visitid= ++qh vertex_visit;
+ FORALLsame_cycle_(samecycle) {
+ if (same->mergeridge)
+ continue;
+ FOREACHvertex_(same->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ qh_setappend (&vertices, vertex);
+ vertex->visitid= qh vertex_visit;
+ vertex->seen= False;
+ }
+ }
+ }
+ trace4((qh ferr, "qh_basevertices: found %d vertices\n",
+ qh_setsize (vertices)));
+ return vertices;
+} /* basevertices */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="checkconnect">-</a>
+
+ qh_checkconnect()
+ check that new facets are connected
+ new facets are on qh.newfacet_list
+
+ notes:
+ this is slow and it changes the order of the facets
+ uses qh.visit_id
+
+ design:
+ move first new facet to end of qh.facet_list
+ for all newly appended facets
+ append unvisited neighbors to end of qh.facet_list
+ for all new facets
+ report error if unvisited
+*/
+void qh_checkconnect (void /* qh newfacet_list */) {
+ facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
+
+ facet= qh newfacet_list;
+ qh_removefacet (facet);
+ qh_appendfacet (facet);
+ facet->visitid= ++qh visit_id;
+ FORALLfacet_(facet) {
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid != qh visit_id) {
+ qh_removefacet (neighbor);
+ qh_appendfacet (neighbor);
+ neighbor->visitid= qh visit_id;
+ }
+ }
+ }
+ FORALLnew_facets {
+ if (newfacet->visitid == qh visit_id)
+ break;
+ fprintf(qh ferr, "qhull error: f%d is not attached to the new facets\n",
+ newfacet->id);
+ errfacet= newfacet;
+ }
+ if (errfacet)
+ qh_errexit (qh_ERRqhull, errfacet, NULL);
+} /* checkconnect */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="checkzero">-</a>
+
+ qh_checkzero( testall )
+ check that facets are clearly convex for qh.DISTround with qh.MERGEexact
+
+ if testall,
+ test all facets for qh.MERGEexact post-merging
+ else
+ test qh.newfacet_list
+
+ if qh.MERGEexact,
+ allows coplanar ridges
+ skips convexity test while qh.ZEROall_ok
+
+ returns:
+ True if all facets !flipped, !dupridge, normal
+ if all horizon facets are simplicial
+ if all vertices are clearly below neighbor
+ if all opposite vertices of horizon are below
+ clears qh.ZEROall_ok if any problems or coplanar facets
+
+ notes:
+ uses qh.vertex_visit
+ horizon facets may define multiple new facets
+
+ design:
+ for all facets in qh.newfacet_list or qh.facet_list
+ check for flagged faults (flipped, etc.)
+ for all facets in qh.newfacet_list or qh.facet_list
+ for each neighbor of facet
+ skip horizon facets for qh.newfacet_list
+ test the opposite vertex
+ if qh.newfacet_list
+ test the other vertices in the facet's horizon facet
+*/
+boolT qh_checkzero (boolT testall) {
+ facetT *facet, *neighbor, **neighborp;
+ facetT *horizon, *facetlist;
+ int neighbor_i;
+ vertexT *vertex, **vertexp;
+ realT dist;
+
+ if (testall)
+ facetlist= qh facet_list;
+ else {
+ facetlist= qh newfacet_list;
+ FORALLfacet_(facetlist) {
+ horizon= SETfirstt_(facet->neighbors, facetT);
+ if (!horizon->simplicial)
+ goto LABELproblem;
+ if (facet->flipped || facet->dupridge || !facet->normal)
+ goto LABELproblem;
+ }
+ if (qh MERGEexact && qh ZEROall_ok) {
+ trace2((qh ferr, "qh_checkzero: skip convexity check until first pre-merge\n"));
+ return True;
+ }
+ }
+ FORALLfacet_(facetlist) {
+ qh vertex_visit++;
+ neighbor_i= 0;
+ horizon= NULL;
+ FOREACHneighbor_(facet) {
+ if (!neighbor_i && !testall) {
+ horizon= neighbor;
+ neighbor_i++;
+ continue; /* horizon facet tested in qh_findhorizon */
+ }
+ vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+ vertex->visitid= qh vertex_visit;
+ zzinc_(Zdistzero);
+ qh_distplane (vertex->point, neighbor, &dist);
+ if (dist >= -qh DISTround) {
+ qh ZEROall_ok= False;
+ if (!qh MERGEexact || testall || dist > qh DISTround)
+ goto LABELnonconvex;
+ }
+ }
+ if (!testall) {
+ FOREACHvertex_(horizon->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ zzinc_(Zdistzero);
+ qh_distplane (vertex->point, facet, &dist);
+ if (dist >= -qh DISTround) {
+ qh ZEROall_ok= False;
+ if (!qh MERGEexact || dist > qh DISTround)
+ goto LABELnonconvex;
+ }
+ break;
+ }
+ }
+ }
+ }
+ trace2((qh ferr, "qh_checkzero: testall %d, facets are %s\n", testall,
+ (qh MERGEexact && !testall) ?
+ "not concave, flipped, or duplicate ridged" : "clearly convex"));
+ return True;
+
+ LABELproblem:
+ qh ZEROall_ok= False;
+ trace2((qh ferr, "qh_checkzero: facet f%d needs pre-merging\n",
+ facet->id));
+ return False;
+
+ LABELnonconvex:
+ trace2((qh ferr, "qh_checkzero: facet f%d and f%d are not clearly convex. v%d dist %.2g\n",
+ facet->id, neighbor->id, vertex->id, dist));
+ return False;
+} /* checkzero */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="compareangle">-</a>
+
+ qh_compareangle( angle1, angle2 )
+ used by qsort() to order merges by angle
+*/
+static int qh_compareangle(const void *p1, const void *p2) {
+ mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
+
+ return ((a->angle > b->angle) ? 1 : -1);
+} /* compareangle */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="comparemerge">-</a>
+
+ qh_comparemerge( merge1, merge2 )
+ used by qsort() to order merges
+*/
+static int qh_comparemerge(const void *p1, const void *p2) {
+ mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
+
+ return (a->type - b->type);
+} /* comparemerge */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="comparevisit">-</a>
+
+ qh_comparevisit( vertex1, vertex2 )
+ used by qsort() to order vertices by their visitid
+*/
+static int qh_comparevisit (const void *p1, const void *p2) {
+ vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
+
+ return (a->visitid - b->visitid);
+} /* comparevisit */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="copynonconvex">-</a>
+
+ qh_copynonconvex( atridge )
+ set non-convex flag on other ridges (if any) between same neighbors
+
+ notes:
+ may be faster if use smaller ridge set
+
+ design:
+ for each ridge of atridge's top facet
+ if ridge shares the same neighbor
+ set nonconvex flag
+*/
+void qh_copynonconvex (ridgeT *atridge) {
+ facetT *facet, *otherfacet;
+ ridgeT *ridge, **ridgep;
+
+ facet= atridge->top;
+ otherfacet= atridge->bottom;
+ FOREACHridge_(facet->ridges) {
+ if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
+ ridge->nonconvex= True;
+ trace4((qh ferr, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
+ atridge->id, ridge->id));
+ break;
+ }
+ }
+} /* copynonconvex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="degen_redundant_facet">-</a>
+
+ qh_degen_redundant_facet( facet )
+ check facet for degen. or redundancy
+
+ notes:
+ bumps vertex_visit
+ called if a facet was redundant but no longer is (qh_merge_degenredundant)
+ qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+
+ see:
+ qh_degen_redundant_neighbors()
+
+ design:
+ test for redundant neighbor
+ test for degenerate facet
+*/
+void qh_degen_redundant_facet (facetT *facet) {
+ vertexT *vertex, **vertexp;
+ facetT *neighbor, **neighborp;
+
+ trace4((qh ferr, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
+ facet->id));
+ FOREACHneighbor_(facet) {
+ qh vertex_visit++;
+ FOREACHvertex_(neighbor->vertices)
+ vertex->visitid= qh vertex_visit;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->visitid != qh vertex_visit)
+ break;
+ }
+ if (!vertex) {
+ qh_appendmergeset (facet, neighbor, MRGredundant, NULL);
+ trace2((qh ferr, "qh_degen_redundant_facet: f%d is contained in f%d. merge\n", facet->id, neighbor->id));
+ return;
+ }
+ }
+ if (qh_setsize (facet->neighbors) < qh hull_dim) {
+ qh_appendmergeset (facet, facet, MRGdegen, NULL);
+ trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
+ }
+} /* degen_redundant_facet */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="degen_redundant_neighbors">-</a>
+
+ qh_degen_redundant_neighbors( facet, delfacet, )
+ append degenerate and redundant neighbors to facet_mergeset
+ if delfacet,
+ only checks neighbors of both delfacet and facet
+ also checks current facet for degeneracy
+
+ notes:
+ bumps vertex_visit
+ called for each qh_mergefacet() and qh_mergecycle()
+ merge and statistics occur in merge_nonconvex
+ qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+ it appends redundant facets after degenerate ones
+
+ a degenerate facet has fewer than hull_dim neighbors
+ a redundant facet's vertices is a subset of its neighbor's vertices
+ tests for redundant merges first (appendmergeset is nop for others)
+ in a merge, only needs to test neighbors of merged facet
+
+ see:
+ qh_merge_degenredundant() and qh_degen_redundant_facet()
+
+ design:
+ test for degenerate facet
+ test for redundant neighbor
+ test for degenerate neighbor
+*/
+void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet) {
+ vertexT *vertex, **vertexp;
+ facetT *neighbor, **neighborp;
+ int size;
+
+ trace4((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n",
+ facet->id, getid_(delfacet)));
+ if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) {
+ qh_appendmergeset (facet, facet, MRGdegen, NULL);
+ trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
+ }
+ if (!delfacet)
+ delfacet= facet;
+ qh vertex_visit++;
+ FOREACHvertex_(facet->vertices)
+ vertex->visitid= qh vertex_visit;
+ FOREACHneighbor_(delfacet) {
+ /* uses early out instead of checking vertex count */
+ if (neighbor == facet)
+ continue;
+ FOREACHvertex_(neighbor->vertices) {
+ if (vertex->visitid != qh vertex_visit)
+ break;
+ }
+ if (!vertex) {
+ qh_appendmergeset (neighbor, facet, MRGredundant, NULL);
+ trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d. merge\n", neighbor->id, facet->id));
+ }
+ }
+ FOREACHneighbor_(delfacet) { /* redundant merges occur first */
+ if (neighbor == facet)
+ continue;
+ if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) {
+ qh_appendmergeset (neighbor, neighbor, MRGdegen, NULL);
+ trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors. Neighbor of f%d.\n", neighbor->id, size, facet->id));
+ }
+ }
+} /* degen_redundant_neighbors */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="find_newvertex">-</a>
+
+ qh_find_newvertex( oldvertex, vertices, ridges )
+ locate new vertex for renaming old vertex
+ vertices is a set of possible new vertices
+ vertices sorted by number of deleted ridges
+
+ returns:
+ newvertex or NULL
+ each ridge includes both vertex and oldvertex
+ vertices sorted by number of deleted ridges
+
+ notes:
+ modifies vertex->visitid
+ new vertex is in one of the ridges
+ renaming will not cause a duplicate ridge
+ renaming will minimize the number of deleted ridges
+ newvertex may not be adjacent in the dual (though unlikely)
+
+ design:
+ for each vertex in vertices
+ set vertex->visitid to number of references in ridges
+ remove unvisited vertices
+ set qh.vertex_visit above all possible values
+ sort vertices by number of references in ridges
+ add each ridge to qh.hash_table
+ for each vertex in vertices
+ look for a vertex that would not cause a duplicate ridge after a rename
+*/
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) {
+ vertexT *vertex, **vertexp;
+ setT *newridges;
+ ridgeT *ridge, **ridgep;
+ int size, hashsize;
+ int hash;
+
+#ifndef qh_NOtrace
+ if (qh IStracing >= 4) {
+ fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ",
+ oldvertex->id);
+ FOREACHvertex_(vertices)
+ fprintf (qh ferr, "v%d ", vertex->id);
+ FOREACHridge_(ridges)
+ fprintf (qh ferr, "r%d ", ridge->id);
+ fprintf (qh ferr, "\n");
+ }
+#endif
+ FOREACHvertex_(vertices)
+ vertex->visitid= 0;
+ FOREACHridge_(ridges) {
+ FOREACHvertex_(ridge->vertices)
+ vertex->visitid++;
+ }
+ FOREACHvertex_(vertices) {
+ if (!vertex->visitid) {
+ qh_setdelnth (vertices, SETindex_(vertices,vertex));
+ vertexp--; /* repeat since deleted this vertex */
+ }
+ }
+ qh vertex_visit += qh_setsize (ridges);
+ if (!qh_setsize (vertices)) {
+ trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n",
+ oldvertex->id));
+ return NULL;
+ }
+ qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices),
+ sizeof (vertexT *), qh_comparevisit);
+ /* can now use qh vertex_visit */
+ if (qh PRINTstatistics) {
+ size= qh_setsize (vertices);
+ zinc_(Zintersect);
+ zadd_(Zintersecttot, size);
+ zmax_(Zintersectmax, size);
+ }
+ hashsize= qh_newhashtable (qh_setsize (ridges));
+ FOREACHridge_(ridges)
+ qh_hashridge (qh hash_table, hashsize, ridge, oldvertex);
+ FOREACHvertex_(vertices) {
+ newridges= qh_vertexridges (vertex);
+ FOREACHridge_(newridges) {
+ if (qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
+ zinc_(Zdupridge);
+ break;
+ }
+ }
+ qh_settempfree (&newridges);
+ if (!ridge)
+ break; /* found a rename */
+ }
+ if (vertex) {
+ /* counted in qh_renamevertex */
+ trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
+ vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges)));
+ }else {
+ zinc_(Zfindfail);
+ trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges) during p%d\n",
+ oldvertex->id, qh furthest_id));
+ }
+ qh_setfree (&qh hash_table);
+ return vertex;
+} /* find_newvertex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="findbest_test">-</a>
+
+ qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
+ test neighbor of facet for qh_findbestneighbor()
+ if testcentrum,
+ tests centrum (assumes it is defined)
+ else
+ tests vertices
+
+ returns:
+ if a better facet (i.e., vertices/centrum of facet closer to neighbor)
+ updates bestfacet, dist, mindist, and maxdist
+*/
+void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+ facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
+ realT dist, mindist, maxdist;
+
+ if (testcentrum) {
+ zzinc_(Zbestdist);
+ qh_distplane(facet->center, neighbor, &dist);
+ dist *= qh hull_dim; /* estimate furthest vertex */
+ if (dist < 0) {
+ maxdist= 0;
+ mindist= dist;
+ dist= -dist;
+ }else
+ maxdist= dist;
+ }else
+ dist= qh_getdistance (facet, neighbor, &mindist, &maxdist);
+ if (dist < *distp) {
+ *bestfacet= neighbor;
+ *mindistp= mindist;
+ *maxdistp= maxdist;
+ *distp= dist;
+ }
+} /* findbest_test */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="findbestneighbor">-</a>
+
+ qh_findbestneighbor( facet, dist, mindist, maxdist )
+ finds best neighbor (least dist) of a facet for merging
+
+ returns:
+ returns min and max distances and their max absolute value
+
+ notes:
+ avoids merging old into new
+ assumes ridge->nonconvex only set on one ridge between a pair of facets
+ could use an early out predicate but not worth it
+
+ design:
+ if a large facet
+ will test centrum
+ else
+ will test vertices
+ if a large facet
+ test nonconvex neighbors for best merge
+ else
+ test all neighbors for the best merge
+ if testing centrum
+ get distance information
+*/
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
+ facetT *neighbor, **neighborp, *bestfacet= NULL;
+ ridgeT *ridge, **ridgep;
+ boolT nonconvex= True, testcentrum= False;
+ int size= qh_setsize (facet->vertices);
+
+ *distp= REALmax;
+ if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
+ testcentrum= True;
+ zinc_(Zbestcentrum);
+ if (!facet->center)
+ facet->center= qh_getcentrum (facet);
+ }
+ if (size > qh hull_dim + qh_BESTnonconvex) {
+ FOREACHridge_(facet->ridges) {
+ if (ridge->nonconvex) {
+ neighbor= otherfacet_(ridge, facet);
+ qh_findbest_test (testcentrum, facet, neighbor,
+ &bestfacet, distp, mindistp, maxdistp);
+ }
+ }
+ }
+ if (!bestfacet) {
+ nonconvex= False;
+ FOREACHneighbor_(facet)
+ qh_findbest_test (testcentrum, facet, neighbor,
+ &bestfacet, distp, mindistp, maxdistp);
+ }
+ if (!bestfacet) {
+ fprintf (qh ferr, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
+
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ if (testcentrum)
+ qh_getdistance (facet, bestfacet, mindistp, maxdistp);
+ trace3((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
+ bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
+ return(bestfacet);
+} /* findbestneighbor */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="flippedmerges">-</a>
+
+ qh_flippedmerges( facetlist, wasmerge )
+ merge flipped facets into best neighbor
+ assumes qh.facet_mergeset at top of temporary stack
+
+ returns:
+ no flipped facets on facetlist
+ sets wasmerge if merge occurred
+ degen/redundant merges passed through
+
+ notes:
+ othermerges not needed since qh.facet_mergeset is empty before & after
+ keep it in case of change
+
+ design:
+ append flipped facets to qh.facetmergeset
+ for each flipped merge
+ find best neighbor
+ merge facet into neighbor
+ merge degenerate and redundant facets
+ remove flipped merges from qh.facet_mergeset
+*/
+void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
+ facetT *facet, *neighbor, *facet1;
+ realT dist, mindist, maxdist;
+ mergeT *merge, **mergep;
+ setT *othermerges;
+ int nummerge=0;
+
+ trace4((qh ferr, "qh_flippedmerges: begin\n"));
+ FORALLfacet_(facetlist) {
+ if (facet->flipped && !facet->visible)
+ qh_appendmergeset (facet, facet, MRGflip, NULL);
+ }
+ othermerges= qh_settemppop(); /* was facet_mergeset */
+ qh facet_mergeset= qh_settemp (qh TEMPsize);
+ qh_settemppush (othermerges);
+ FOREACHmerge_(othermerges) {
+ facet1= merge->facet1;
+ if (merge->type != MRGflip || facet1->visible)
+ continue;
+ if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist);
+ trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
+ facet1->id, neighbor->id, dist, qh furthest_id));
+ qh_mergefacet (facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
+ nummerge++;
+ if (qh PRINTstatistics) {
+ zinc_(Zflipped);
+ wadd_(Wflippedtot, dist);
+ wmax_(Wflippedmax, dist);
+ }
+ qh_merge_degenredundant();
+ }
+ FOREACHmerge_(othermerges) {
+ if (merge->facet1->visible || merge->facet2->visible)
+ qh_memfree (merge, sizeof(mergeT));
+ else
+ qh_setappend (&qh facet_mergeset, merge);
+ }
+ qh_settempfree (&othermerges);
+ if (nummerge)
+ *wasmerge= True;
+ trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
+} /* flippedmerges */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="forcedmerges">-</a>
+
+ qh_forcedmerges( wasmerge )
+ merge duplicated ridges
+
+ returns:
+ removes all duplicate ridges on facet_mergeset
+ wasmerge set if merge
+ qh.facet_mergeset may include non-forced merges (none for now)
+ qh.degen_mergeset includes degen/redun merges
+
+ notes:
+ duplicate ridges occur when the horizon is pinched,
+ i.e. a subridge occurs in more than two horizon ridges.
+ could rename vertices that pinch the horizon
+ assumes qh_merge_degenredundant() has not be called
+ othermerges isn't needed since facet_mergeset is empty afterwards
+ keep it in case of change
+
+ design:
+ for each duplicate ridge
+ find current facets by chasing f.replace links
+ determine best direction for facet
+ merge one facet into the other
+ remove duplicate ridges from qh.facet_mergeset
+*/
+void qh_forcedmerges(boolT *wasmerge) {
+ facetT *facet1, *facet2;
+ mergeT *merge, **mergep;
+ realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
+ setT *othermerges;
+ int nummerge=0, numflip=0;
+
+ if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ trace4((qh ferr, "qh_forcedmerges: begin\n"));
+ othermerges= qh_settemppop(); /* was facet_mergeset */
+ qh facet_mergeset= qh_settemp (qh TEMPsize);
+ qh_settemppush (othermerges);
+ FOREACHmerge_(othermerges) {
+ if (merge->type != MRGridge)
+ continue;
+ facet1= merge->facet1;
+ facet2= merge->facet2;
+ while (facet1->visible) /* must exist, no qh_merge_degenredunant */
+ facet1= facet1->f.replace; /* previously merged facet */
+ while (facet2->visible)
+ facet2= facet2->f.replace; /* previously merged facet */
+ if (facet1 == facet2)
+ continue;
+ if (!qh_setin (facet2->neighbors, facet1)) {
+ fprintf (qh ferr, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
+ merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
+ qh_errexit2 (qh_ERRqhull, facet1, facet2);
+ }
+ if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1);
+ dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2);
+ trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
+ facet1->id, facet2->id, dist1, dist2, qh furthest_id));
+ if (dist1 < dist2)
+ qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
+ else {
+ qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
+ dist1= dist2;
+ facet1= facet2;
+ }
+ if (facet1->flipped) {
+ zinc_(Zmergeflipdup);
+ numflip++;
+ }else
+ nummerge++;
+ if (qh PRINTstatistics) {
+ zinc_(Zduplicate);
+ wadd_(Wduplicatetot, dist1);
+ wmax_(Wduplicatemax, dist1);
+ }
+ }
+ FOREACHmerge_(othermerges) {
+ if (merge->type == MRGridge)
+ qh_memfree (merge, sizeof(mergeT));
+ else
+ qh_setappend (&qh facet_mergeset, merge);
+ }
+ qh_settempfree (&othermerges);
+ if (nummerge)
+ *wasmerge= True;
+ trace1((qh ferr, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n",
+ nummerge, numflip));
+} /* forcedmerges */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="getmergeset">-</a>
+
+ qh_getmergeset( facetlist )
+ determines nonconvex facets on facetlist
+ tests !tested ridges and nonconvex ridges of !tested facets
+
+ returns:
+ returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
+ all ridges tested
+
+ notes:
+ assumes no nonconvex ridges with both facets tested
+ uses facet->tested/ridge->tested to prevent duplicate tests
+ can not limit tests to modified ridges since the centrum changed
+ uses qh.visit_id
+
+ see:
+ qh_getmergeset_initial()
+
+ design:
+ for each facet on facetlist
+ for each ridge of facet
+ if untested ridge
+ test ridge for convexity
+ if non-convex
+ append ridge to qh.facet_mergeset
+ sort qh.facet_mergeset by angle
+*/
+void qh_getmergeset(facetT *facetlist) {
+ facetT *facet, *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+ int nummerges;
+
+ nummerges= qh_setsize (qh facet_mergeset);
+ trace4((qh ferr, "qh_getmergeset: started.\n"));
+ qh visit_id++;
+ FORALLfacet_(facetlist) {
+ if (facet->tested)
+ continue;
+ facet->visitid= qh visit_id;
+ facet->tested= True; /* must be non-simplicial due to merge */
+ FOREACHneighbor_(facet)
+ neighbor->seen= False;
+ FOREACHridge_(facet->ridges) {
+ if (ridge->tested && !ridge->nonconvex)
+ continue;
+ /* if tested & nonconvex, need to append merge */
+ neighbor= otherfacet_(ridge, facet);
+ if (neighbor->seen) {
+ ridge->tested= True;
+ ridge->nonconvex= False;
+ }else if (neighbor->visitid != qh visit_id) {
+ ridge->tested= True;
+ ridge->nonconvex= False;
+ neighbor->seen= True; /* only one ridge is marked nonconvex */
+ if (qh_test_appendmerge (facet, neighbor))
+ ridge->nonconvex= True;
+ }
+ }
+ }
+ nummerges= qh_setsize (qh facet_mergeset);
+ if (qh ANGLEmerge)
+ qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
+ else
+ qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
+ if (qh POSTmerging) {
+ zadd_(Zmergesettot2, nummerges);
+ }else {
+ zadd_(Zmergesettot, nummerges);
+ zmax_(Zmergesetmax, nummerges);
+ }
+ trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges));
+} /* getmergeset */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="getmergeset_initial">-</a>
+
+ qh_getmergeset_initial( facetlist )
+ determine initial qh.facet_mergeset for facets
+ tests all facet/neighbor pairs on facetlist
+
+ returns:
+ sorted qh.facet_mergeset with nonconvex ridges
+ sets facet->tested, ridge->tested, and ridge->nonconvex
+
+ notes:
+ uses visit_id, assumes ridge->nonconvex is False
+
+ see:
+ qh_getmergeset()
+
+ design:
+ for each facet on facetlist
+ for each untested neighbor of facet
+ test facet and neighbor for convexity
+ if non-convex
+ append merge to qh.facet_mergeset
+ mark one of the ridges as nonconvex
+ sort qh.facet_mergeset by angle
+*/
+void qh_getmergeset_initial (facetT *facetlist) {
+ facetT *facet, *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+ int nummerges;
+
+ qh visit_id++;
+ FORALLfacet_(facetlist) {
+ facet->visitid= qh visit_id;
+ facet->tested= True;
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid != qh visit_id) {
+ if (qh_test_appendmerge (facet, neighbor)) {
+ FOREACHridge_(neighbor->ridges) {
+ if (facet == otherfacet_(ridge, neighbor)) {
+ ridge->nonconvex= True;
+ break; /* only one ridge is marked nonconvex */
+ }
+ }
+ }
+ }
+ }
+ FOREACHridge_(facet->ridges)
+ ridge->tested= True;
+ }
+ nummerges= qh_setsize (qh facet_mergeset);
+ if (qh ANGLEmerge)
+ qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
+ else
+ qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
+ if (qh POSTmerging) {
+ zadd_(Zmergeinittot2, nummerges);
+ }else {
+ zadd_(Zmergeinittot, nummerges);
+ zmax_(Zmergeinitmax, nummerges);
+ }
+ trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges));
+} /* getmergeset_initial */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="hashridge">-</a>
+
+ qh_hashridge( hashtable, hashsize, ridge, oldvertex )
+ add ridge to hashtable without oldvertex
+
+ notes:
+ assumes hashtable is large enough
+
+ design:
+ determine hash value for ridge without oldvertex
+ find next empty slot for ridge
+*/
+void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
+ int hash;
+ ridgeT *ridgeA;
+
+ hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
+ while (True) {
+ if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+ SETelem_(hashtable, hash)= ridge;
+ break;
+ }else if (ridgeA == ridge)
+ break;
+ if (++hash == hashsize)
+ hash= 0;
+ }
+} /* hashridge */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="hashridge_find">-</a>
+
+ qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
+ returns matching ridge without oldvertex in hashtable
+ for ridge without vertex
+ if oldvertex is NULL
+ matches with any one skip
+
+ returns:
+ matching ridge or NULL
+ if no match,
+ if ridge already in table
+ hashslot= -1
+ else
+ hashslot= next NULL index
+
+ notes:
+ assumes hashtable is large enough
+ can't match ridge to itself
+
+ design:
+ get hash value for ridge without vertex
+ for each hashslot
+ return match if ridge matches ridgeA without oldvertex
+*/
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge,
+ vertexT *vertex, vertexT *oldvertex, int *hashslot) {
+ int hash;
+ ridgeT *ridgeA;
+
+ *hashslot= 0;
+ zinc_(Zhashridge);
+ hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
+ while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+ if (ridgeA == ridge)
+ *hashslot= -1;
+ else {
+ zinc_(Zhashridgetest);
+ if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex))
+ return ridgeA;
+ }
+ if (++hash == hashsize)
+ hash= 0;
+ }
+ if (!*hashslot)
+ *hashslot= hash;
+ return NULL;
+} /* hashridge_find */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="makeridges">-</a>
+
+ qh_makeridges( facet )
+ creates explicit ridges between simplicial facets
+
+ returns:
+ facet with ridges and without qh_MERGEridge
+ ->simplicial is False
+
+ notes:
+ allows qh_MERGEridge flag
+ uses existing ridges
+ duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
+
+ see:
+ qh_mergecycle_ridges()
+
+ design:
+ look for qh_MERGEridge neighbors
+ mark neighbors that already have ridges
+ for each unprocessed neighbor of facet
+ create a ridge for neighbor and facet
+ if any qh_MERGEridge neighbors
+ delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
+*/
+void qh_makeridges(facetT *facet) {
+ facetT *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+ int neighbor_i, neighbor_n;
+ boolT toporient, mergeridge= False;
+
+ if (!facet->simplicial)
+ return;
+ trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id));
+ facet->simplicial= False;
+ FOREACHneighbor_(facet) {
+ if (neighbor == qh_MERGEridge)
+ mergeridge= True;
+ else
+ neighbor->seen= False;
+ }
+ FOREACHridge_(facet->ridges)
+ otherfacet_(ridge, facet)->seen= True;
+ FOREACHneighbor_i_(facet) {
+ if (neighbor == qh_MERGEridge)
+ continue; /* fixed by qh_mark_dupridges */
+ else if (!neighbor->seen) { /* no current ridges */
+ ridge= qh_newridge();
+ ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+ neighbor_i, 0);
+ toporient= facet->toporient ^ (neighbor_i & 0x1);
+ if (toporient) {
+ ridge->top= facet;
+ ridge->bottom= neighbor;
+ }else {
+ ridge->top= neighbor;
+ ridge->bottom= facet;
+ }
+#if 0 /* this also works */
+ flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
+ if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
+ ridge->top= neighbor;
+ ridge->bottom= facet;
+ }else {
+ ridge->top= facet;
+ ridge->bottom= neighbor;
+ }
+#endif
+ qh_setappend(&(facet->ridges), ridge);
+ qh_setappend(&(neighbor->ridges), ridge);
+ }
+ }
+ if (mergeridge) {
+ while (qh_setdel (facet->neighbors, qh_MERGEridge))
+ ; /* delete each one */
+ }
+} /* makeridges */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mark_dupridges">-</a>
+
+ qh_mark_dupridges( facetlist )
+ add duplicated ridges to qh.facet_mergeset
+ facet->dupridge is true
+
+ returns:
+ duplicate ridges on qh.facet_mergeset
+ ->mergeridge/->mergeridge2 set
+ duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
+ no MERGEridges in neighbor sets
+
+ notes:
+ duplicate ridges occur when the horizon is pinched,
+ i.e. a subridge occurs in more than two horizon ridges.
+ could rename vertices that pinch the horizon
+ uses qh.visit_id
+
+ design:
+ for all facets on facetlist
+ if facet contains a duplicate ridge
+ for each neighbor of facet
+ if neighbor marked qh_MERGEridge (one side of the merge)
+ set facet->mergeridge
+ else
+ if neighbor contains a duplicate ridge
+ and the back link is qh_MERGEridge
+ append duplicate ridge to qh.facet_mergeset
+ for each duplicate ridge
+ make ridge sets in preparation for merging
+ remove qh_MERGEridge from neighbor set
+ for each duplicate ridge
+ restore the missing neighbor from the neighbor set that was qh_MERGEridge
+ add the missing ridge for this neighbor
+*/
+void qh_mark_dupridges(facetT *facetlist) {
+ facetT *facet, *neighbor, **neighborp;
+ int nummerge=0;
+ mergeT *merge, **mergep;
+
+
+ trace4((qh ferr, "qh_mark_dupridges: identify duplicate ridges\n"));
+ FORALLfacet_(facetlist) {
+ if (facet->dupridge) {
+ FOREACHneighbor_(facet) {
+ if (neighbor == qh_MERGEridge) {
+ facet->mergeridge= True;
+ continue;
+ }
+ if (neighbor->dupridge
+ && !qh_setin (neighbor->neighbors, facet)) { /* qh_MERGEridge */
+ qh_appendmergeset (facet, neighbor, MRGridge, NULL);
+ facet->mergeridge2= True;
+ facet->mergeridge= True;
+ nummerge++;
+ }
+ }
+ }
+ }
+ if (!nummerge)
+ return;
+ FORALLfacet_(facetlist) { /* gets rid of qh_MERGEridge */
+ if (facet->mergeridge && !facet->mergeridge2)
+ qh_makeridges (facet);
+ }
+ FOREACHmerge_(qh facet_mergeset) { /* restore the missing neighbors */
+ if (merge->type == MRGridge) {
+ qh_setappend (&merge->facet2->neighbors, merge->facet1);
+ qh_makeridges (merge->facet1); /* and the missing ridges */
+ }
+ }
+ trace1((qh ferr, "qh_mark_dupridges: found %d duplicated ridges\n",
+ nummerge));
+} /* mark_dupridges */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="maydropneighbor">-</a>
+
+ qh_maydropneighbor( facet )
+ drop neighbor relationship if no ridge between facet and neighbor
+
+ returns:
+ neighbor sets updated
+ appends degenerate facets to qh.facet_mergeset
+
+ notes:
+ won't cause redundant facets since vertex inclusion is the same
+ may drop vertex and neighbor if no ridge
+ uses qh.visit_id
+
+ design:
+ visit all neighbors with ridges
+ for each unvisited neighbor of facet
+ delete neighbor and facet from the neighbor sets
+ if neighbor becomes degenerate
+ append neighbor to qh.degen_mergeset
+ if facet is degenerate
+ append facet to qh.degen_mergeset
+*/
+void qh_maydropneighbor (facetT *facet) {
+ ridgeT *ridge, **ridgep;
+ realT angledegen= qh_ANGLEdegen;
+ facetT *neighbor, **neighborp;
+
+ qh visit_id++;
+ trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
+ facet->id));
+ FOREACHridge_(facet->ridges) {
+ ridge->top->visitid= qh visit_id;
+ ridge->bottom->visitid= qh visit_id;
+ }
+ FOREACHneighbor_(facet) {
+ if (neighbor->visitid != qh visit_id) {
+ trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
+ facet->id, neighbor->id, qh furthest_id));
+ zinc_(Zdropneighbor);
+ qh_setdel (facet->neighbors, neighbor);
+ neighborp--; /* repeat, deleted a neighbor */
+ qh_setdel (neighbor->neighbors, facet);
+ if (qh_setsize (neighbor->neighbors) < qh hull_dim) {
+ zinc_(Zdropdegen);
+ qh_appendmergeset (neighbor, neighbor, MRGdegen, &angledegen);
+ trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
+ }
+ }
+ }
+ if (qh_setsize (facet->neighbors) < qh hull_dim) {
+ zinc_(Zdropdegen);
+ qh_appendmergeset (facet, facet, MRGdegen, &angledegen);
+ trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
+ }
+} /* maydropneighbor */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="merge_degenredundant">-</a>
+
+ qh_merge_degenredundant()
+ merge all degenerate and redundant facets
+ qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
+
+ returns:
+ number of merges performed
+ resets facet->degenerate/redundant
+ if deleted (visible) facet has no neighbors
+ sets ->f.replace to NULL
+
+ notes:
+ redundant merges happen before degenerate ones
+ merging and renaming vertices can result in degen/redundant facets
+
+ design:
+ for each merge on qh.degen_mergeset
+ if redundant merge
+ if non-redundant facet merged into redundant facet
+ recheck facet for redundancy
+ else
+ merge redundant facet into other facet
+*/
+int qh_merge_degenredundant (void) {
+ int size;
+ mergeT *merge;
+ facetT *bestneighbor, *facet1, *facet2;
+ realT dist, mindist, maxdist;
+ vertexT *vertex, **vertexp;
+ int nummerges= 0;
+ mergeType mergetype;
+
+ while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
+ facet1= merge->facet1;
+ facet2= merge->facet2;
+ mergetype= merge->type;
+ qh_memfree (merge, sizeof(mergeT));
+ if (facet1->visible)
+ continue;
+ facet1->degenerate= False;
+ facet1->redundant= False;
+ if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ if (mergetype == MRGredundant) {
+ zinc_(Zneighbor);
+ while (facet2->visible) {
+ if (!facet2->f.replace) {
+ fprintf (qh ferr, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
+ facet1->id, facet2->id);
+ qh_errexit2 (qh_ERRqhull, facet1, facet2);
+ }
+ facet2= facet2->f.replace;
+ }
+ if (facet1 == facet2) {
+ qh_degen_redundant_facet (facet1); /* in case of others */
+ continue;
+ }
+ trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
+ facet1->id, facet2->id));
+ qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
+ /* merge distance is already accounted for */
+ nummerges++;
+ }else { /* mergetype == MRGdegen, other merges may have fixed */
+ if (!(size= qh_setsize (facet1->neighbors))) {
+ zinc_(Zdelfacetdup);
+ trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors. Deleted\n", facet1->id));
+ qh_willdelete (facet1, NULL);
+ FOREACHvertex_(facet1->vertices) {
+ qh_setdel (vertex->neighbors, facet1);
+ if (!SETfirst_(vertex->neighbors)) {
+ zinc_(Zdegenvertex);
+ trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
+ vertex->id, facet1->id));
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+ }
+ }
+ nummerges++;
+ }else if (size < qh hull_dim) {
+ bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
+ trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
+ facet1->id, size, bestneighbor->id, dist));
+ qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+ nummerges++;
+ if (qh PRINTstatistics) {
+ zinc_(Zdegen);
+ wadd_(Wdegentot, dist);
+ wmax_(Wdegenmax, dist);
+ }
+ } /* else, another merge fixed the degeneracy and redundancy tested */
+ }
+ }
+ return nummerges;
+} /* merge_degenredundant */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="merge_nonconvex">-</a>
+
+ qh_merge_nonconvex( facet1, facet2, mergetype )
+ remove non-convex ridge between facet1 into facet2
+ mergetype gives why the facet's are non-convex
+
+ returns:
+ merges one of the facets into the best neighbor
+
+ design:
+ if one of the facets is a new facet
+ prefer merging new facet into old facet
+ find best neighbors for both facets
+ merge the nearest facet into its best neighbor
+ update the statistics
+*/
+void qh_merge_nonconvex (facetT *facet1, facetT *facet2, mergeType mergetype) {
+ facetT *bestfacet, *bestneighbor, *neighbor;
+ realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
+
+ if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ trace3((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
+ zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
+ /* concave or coplanar */
+ if (!facet1->newfacet) {
+ bestfacet= facet2; /* avoid merging old facet if new is ok */
+ facet2= facet1;
+ facet1= bestfacet;
+ }else
+ bestfacet= facet1;
+ bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
+ neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
+ if (dist < dist2) {
+ qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+ }else if (qh AVOIDold && !facet2->newfacet
+ && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
+ || dist * 1.5 < dist2)) {
+ zinc_(Zavoidold);
+ wadd_(Wavoidoldtot, dist);
+ wmax_(Wavoidoldmax, dist);
+ trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g. Use f%d dist %2.2g instead\n",
+ facet2->id, dist2, facet1->id, dist2));
+ qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+ }else {
+ qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
+ dist= dist2;
+ }
+ if (qh PRINTstatistics) {
+ if (mergetype == MRGanglecoplanar) {
+ zinc_(Zacoplanar);
+ wadd_(Wacoplanartot, dist);
+ wmax_(Wacoplanarmax, dist);
+ }else if (mergetype == MRGconcave) {
+ zinc_(Zconcave);
+ wadd_(Wconcavetot, dist);
+ wmax_(Wconcavemax, dist);
+ }else { /* MRGcoplanar */
+ zinc_(Zcoplanar);
+ wadd_(Wcoplanartot, dist);
+ wmax_(Wcoplanarmax, dist);
+ }
+ }
+} /* merge_nonconvex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle">-</a>
+
+ qh_mergecycle( samecycle, newfacet )
+ merge a cycle of facets starting at samecycle into a newfacet
+ newfacet is a horizon facet with ->normal
+ samecycle facets are simplicial from an apex
+
+ returns:
+ initializes vertex neighbors on first merge
+ samecycle deleted (placed on qh.visible_list)
+ newfacet at end of qh.facet_list
+ deleted vertices on qh.del_vertices
+
+ see:
+ qh_mergefacet()
+ called by qh_mergecycle_all() for multiple, same cycle facets
+
+ design:
+ make vertex neighbors if necessary
+ make ridges for newfacet
+ merge neighbor sets of samecycle into newfacet
+ merge ridges of samecycle into newfacet
+ merge vertex neighbors of samecycle into newfacet
+ make apex of samecycle the apex of newfacet
+ if newfacet wasn't a new facet
+ add its vertices to qh.newvertex_list
+ delete samecycle facets a make newfacet a newfacet
+*/
+void qh_mergecycle (facetT *samecycle, facetT *newfacet) {
+ int traceonce= False, tracerestore= 0;
+ vertexT *apex;
+#ifndef qh_NOtrace
+ facetT *same;
+#endif
+
+ if (newfacet->tricoplanar) {
+ if (!qh TRInormals) {
+ fprintf (qh ferr, "qh_mergecycle: does not work for tricoplanar facets. Use option 'Q11'\n");
+ qh_errexit (qh_ERRqhull, newfacet, NULL);
+ }
+ newfacet->tricoplanar= False;
+ newfacet->keepcentrum= False;
+ }
+ if (!qh VERTEXneighbors)
+ qh_vertexneighbors();
+ zzinc_(Ztotmerge);
+ if (qh REPORTfreq2 && qh POSTmerging) {
+ if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+ qh_tracemerging();
+ }
+#ifndef qh_NOtrace
+ if (qh TRACEmerge == zzval_(Ztotmerge))
+ qhmem.IStracing= qh IStracing= qh TRACElevel;
+ trace2((qh ferr, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n",
+ zzval_(Ztotmerge), samecycle->id, newfacet->id));
+ if (newfacet == qh tracefacet) {
+ tracerestore= qh IStracing;
+ qh IStracing= 4;
+ fprintf (qh ferr, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
+ zzval_(Ztotmerge), samecycle->id, newfacet->id, qh furthest_id);
+ traceonce= True;
+ }
+ if (qh IStracing >=4) {
+ fprintf (qh ferr, " same cycle:");
+ FORALLsame_cycle_(samecycle)
+ fprintf(qh ferr, " f%d", same->id);
+ fprintf (qh ferr, "\n");
+ }
+ if (qh IStracing >=4)
+ qh_errprint ("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
+#endif /* !qh_NOtrace */
+ apex= SETfirstt_(samecycle->vertices, vertexT);
+ qh_makeridges (newfacet);
+ qh_mergecycle_neighbors (samecycle, newfacet);
+ qh_mergecycle_ridges (samecycle, newfacet);
+ qh_mergecycle_vneighbors (samecycle, newfacet);
+ if (SETfirstt_(newfacet->vertices, vertexT) != apex)
+ qh_setaddnth (&newfacet->vertices, 0, apex); /* apex has last id */
+ if (!newfacet->newfacet)
+ qh_newvertices (newfacet->vertices);
+ qh_mergecycle_facets (samecycle, newfacet);
+ qh_tracemerge (samecycle, newfacet);
+ /* check for degen_redundant_neighbors after qh_forcedmerges() */
+ if (traceonce) {
+ fprintf (qh ferr, "qh_mergecycle: end of trace facet\n");
+ qh IStracing= tracerestore;
+ }
+} /* mergecycle */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle_all">-</a>
+
+ qh_mergecycle_all( facetlist, wasmerge )
+ merge all samecycles of coplanar facets into horizon
+ don't merge facets with ->mergeridge (these already have ->normal)
+ all facets are simplicial from apex
+ all facet->cycledone == False
+
+ returns:
+ all newfacets merged into coplanar horizon facets
+ deleted vertices on qh.del_vertices
+ sets wasmerge if any merge
+
+ see:
+ calls qh_mergecycle for multiple, same cycle facets
+
+ design:
+ for each facet on facetlist
+ skip facets with duplicate ridges and normals
+ check that facet is in a samecycle (->mergehorizon)
+ if facet only member of samecycle
+ sets vertex->delridge for all vertices except apex
+ merge facet into horizon
+ else
+ mark all facets in samecycle
+ remove facets with duplicate ridges from samecycle
+ merge samecycle into horizon (deletes facets from facetlist)
+*/
+void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge) {
+ facetT *facet, *same, *prev, *horizon;
+ facetT *samecycle= NULL, *nextfacet, *nextsame;
+ vertexT *apex, *vertex, **vertexp;
+ int cycles=0, total=0, facets, nummerge;
+
+ trace2((qh ferr, "qh_mergecycle_all: begin\n"));
+ for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
+ if (facet->normal)
+ continue;
+ if (!facet->mergehorizon) {
+ fprintf (qh ferr, "qh_mergecycle_all: f%d without normal\n", facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ horizon= SETfirstt_(facet->neighbors, facetT);
+ if (facet->f.samecycle == facet) {
+ zinc_(Zonehorizon);
+ /* merge distance done in qh_findhorizon */
+ apex= SETfirstt_(facet->vertices, vertexT);
+ FOREACHvertex_(facet->vertices) {
+ if (vertex != apex)
+ vertex->delridge= True;
+ }
+ horizon->f.newcycle= NULL;
+ qh_mergefacet (facet, horizon, NULL, NULL, qh_MERGEapex);
+ }else {
+ samecycle= facet;
+ facets= 0;
+ prev= facet;
+ for (same= facet->f.samecycle; same; /* FORALLsame_cycle_(facet) */
+ same= (same == facet ? NULL :nextsame)) { /* ends at facet */
+ nextsame= same->f.samecycle;
+ if (same->cycledone || same->visible)
+ qh_infiniteloop (same);
+ same->cycledone= True;
+ if (same->normal) {
+ prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
+ same->f.samecycle= NULL;
+ }else {
+ prev= same;
+ facets++;
+ }
+ }
+ while (nextfacet && nextfacet->cycledone) /* will delete samecycle */
+ nextfacet= nextfacet->next;
+ horizon->f.newcycle= NULL;
+ qh_mergecycle (samecycle, horizon);
+ nummerge= horizon->nummerge + facets;
+ if (nummerge > qh_MAXnummerge)
+ horizon->nummerge= qh_MAXnummerge;
+ else
+ horizon->nummerge= nummerge;
+ zzinc_(Zcyclehorizon);
+ total += facets;
+ zzadd_(Zcyclefacettot, facets);
+ zmax_(Zcyclefacetmax, facets);
+ }
+ cycles++;
+ }
+ if (cycles)
+ *wasmerge= True;
+ trace1((qh ferr, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
+} /* mergecycle_all */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle_facets">-</a>
+
+ qh_mergecycle_facets( samecycle, newfacet )
+ finish merge of samecycle into newfacet
+
+ returns:
+ samecycle prepended to visible_list for later deletion and partitioning
+ each facet->f.replace == newfacet
+
+ newfacet moved to end of qh.facet_list
+ makes newfacet a newfacet (get's facet1->id if it was old)
+ sets newfacet->newmerge
+ clears newfacet->center (unless merging into a large facet)
+ clears newfacet->tested and ridge->tested for facet1
+
+ adds neighboring facets to facet_mergeset if redundant or degenerate
+
+ design:
+ make newfacet a new facet and set its flags
+ move samecycle facets to qh.visible_list for later deletion
+ unless newfacet is large
+ remove its centrum
+*/
+void qh_mergecycle_facets (facetT *samecycle, facetT *newfacet) {
+ facetT *same, *next;
+
+ trace4((qh ferr, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));
+ qh_removefacet(newfacet); /* append as a newfacet to end of qh facet_list */
+ qh_appendfacet(newfacet);
+ newfacet->newfacet= True;
+ newfacet->simplicial= False;
+ newfacet->newmerge= True;
+
+ for (same= samecycle->f.samecycle; same; same= (same == samecycle ? NULL : next)) {
+ next= same->f.samecycle; /* reused by willdelete */
+ qh_willdelete (same, newfacet);
+ }
+ if (newfacet->center
+ && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
+ qh_memfree (newfacet->center, qh normal_size);
+ newfacet->center= NULL;
+ }
+ trace3((qh ferr, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n",
+ samecycle->id, newfacet->id));
+} /* mergecycle_facets */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle_neighbors">-</a>
+
+ qh_mergecycle_neighbors( samecycle, newfacet )
+ add neighbors for samecycle facets to newfacet
+
+ returns:
+ newfacet with updated neighbors and vice-versa
+ newfacet has ridges
+ all neighbors of newfacet marked with qh.visit_id
+ samecycle facets marked with qh.visit_id-1
+ ridges updated for simplicial neighbors of samecycle with a ridge
+
+ notes:
+ assumes newfacet not in samecycle
+ usually, samecycle facets are new, simplicial facets without internal ridges
+ not so if horizon facet is coplanar to two different samecycles
+
+ see:
+ qh_mergeneighbors()
+
+ design:
+ check samecycle
+ delete neighbors from newfacet that are also in samecycle
+ for each neighbor of a facet in samecycle
+ if neighbor is simplicial
+ if first visit
+ move the neighbor relation to newfacet
+ update facet links for its ridges
+ else
+ make ridges for neighbor
+ remove samecycle reference
+ else
+ update neighbor sets
+*/
+void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
+ facetT *same, *neighbor, **neighborp;
+ int delneighbors= 0, newneighbors= 0;
+ unsigned int samevisitid;
+ ridgeT *ridge, **ridgep;
+
+ samevisitid= ++qh visit_id;
+ FORALLsame_cycle_(samecycle) {
+ if (same->visitid == samevisitid || same->visible)
+ qh_infiniteloop (samecycle);
+ same->visitid= samevisitid;
+ }
+ newfacet->visitid= ++qh visit_id;
+ trace4((qh ferr, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));
+ FOREACHneighbor_(newfacet) {
+ if (neighbor->visitid == samevisitid) {
+ SETref_(neighbor)= NULL; /* samecycle neighbors deleted */
+ delneighbors++;
+ }else
+ neighbor->visitid= qh visit_id;
+ }
+ qh_setcompact (newfacet->neighbors);
+
+ trace4((qh ferr, "qh_mergecycle_neighbors: update neighbors\n"));
+ FORALLsame_cycle_(samecycle) {
+ FOREACHneighbor_(same) {
+ if (neighbor->visitid == samevisitid)
+ continue;
+ if (neighbor->simplicial) {
+ if (neighbor->visitid != qh visit_id) {
+ qh_setappend (&newfacet->neighbors, neighbor);
+ qh_setreplace (neighbor->neighbors, same, newfacet);
+ newneighbors++;
+ neighbor->visitid= qh visit_id;
+ FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
+ if (ridge->top == same) {
+ ridge->top= newfacet;
+ break;
+ }else if (ridge->bottom == same) {
+ ridge->bottom= newfacet;
+ break;
+ }
+ }
+ }else {
+ qh_makeridges (neighbor);
+ qh_setdel (neighbor->neighbors, same);
+ /* same can't be horizon facet for neighbor */
+ }
+ }else { /* non-simplicial neighbor */
+ qh_setdel (neighbor->neighbors, same);
+ if (neighbor->visitid != qh visit_id) {
+ qh_setappend (&neighbor->neighbors, newfacet);
+ qh_setappend (&newfacet->neighbors, neighbor);
+ neighbor->visitid= qh visit_id;
+ newneighbors++;
+ }
+ }
+ }
+ }
+ trace2((qh ferr, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n",
+ delneighbors, newneighbors));
+} /* mergecycle_neighbors */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle_ridges">-</a>
+
+ qh_mergecycle_ridges( samecycle, newfacet )
+ add ridges/neighbors for facets in samecycle to newfacet
+ all new/old neighbors of newfacet marked with qh.visit_id
+ facets in samecycle marked with qh.visit_id-1
+ newfacet marked with qh.visit_id
+
+ returns:
+ newfacet has merged ridges
+
+ notes:
+ ridge already updated for simplicial neighbors of samecycle with a ridge
+
+ see:
+ qh_mergeridges()
+ qh_makeridges()
+
+ design:
+ remove ridges between newfacet and samecycle
+ for each facet in samecycle
+ for each ridge in facet
+ update facet pointers in ridge
+ skip ridges processed in qh_mergecycle_neighors
+ free ridges between newfacet and samecycle
+ free ridges between facets of samecycle (on 2nd visit)
+ append remaining ridges to newfacet
+ if simpilicial facet
+ for each neighbor of facet
+ if simplicial facet
+ and not samecycle facet or newfacet
+ make ridge between neighbor and newfacet
+*/
+void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
+ facetT *same, *neighbor= NULL;
+ int numold=0, numnew=0;
+ int neighbor_i, neighbor_n;
+ unsigned int samevisitid;
+ ridgeT *ridge, **ridgep;
+ boolT toporient;
+ void **freelistp; /* used !qh_NOmem */
+
+ trace4((qh ferr, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));
+ samevisitid= qh visit_id -1;
+ FOREACHridge_(newfacet->ridges) {
+ neighbor= otherfacet_(ridge, newfacet);
+ if (neighbor->visitid == samevisitid)
+ SETref_(ridge)= NULL; /* ridge free'd below */
+ }
+ qh_setcompact (newfacet->ridges);
+
+ trace4((qh ferr, "qh_mergecycle_ridges: add ridges to newfacet\n"));
+ FORALLsame_cycle_(samecycle) {
+ FOREACHridge_(same->ridges) {
+ if (ridge->top == same) {
+ ridge->top= newfacet;
+ neighbor= ridge->bottom;
+ }else if (ridge->bottom == same) {
+ ridge->bottom= newfacet;
+ neighbor= ridge->top;
+ }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
+ qh_setappend (&newfacet->ridges, ridge);
+ numold++; /* already set by qh_mergecycle_neighbors */
+ continue;
+ }else {
+ fprintf (qh ferr, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
+ qh_errexit (qh_ERRqhull, NULL, ridge);
+ }
+ if (neighbor == newfacet) {
+ qh_setfree(&(ridge->vertices));
+ qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+ numold++;
+ }else if (neighbor->visitid == samevisitid) {
+ qh_setdel (neighbor->ridges, ridge);
+ qh_setfree(&(ridge->vertices));
+ qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+ numold++;
+ }else {
+ qh_setappend (&newfacet->ridges, ridge);
+ numold++;
+ }
+ }
+ if (same->ridges)
+ qh_settruncate (same->ridges, 0);
+ if (!same->simplicial)
+ continue;
+ FOREACHneighbor_i_(same) { /* note: !newfact->simplicial */
+ if (neighbor->visitid != samevisitid && neighbor->simplicial) {
+ ridge= qh_newridge();
+ ridge->vertices= qh_setnew_delnthsorted (same->vertices, qh hull_dim,
+ neighbor_i, 0);
+ toporient= same->toporient ^ (neighbor_i & 0x1);
+ if (toporient) {
+ ridge->top= newfacet;
+ ridge->bottom= neighbor;
+ }else {
+ ridge->top= neighbor;
+ ridge->bottom= newfacet;
+ }
+ qh_setappend(&(newfacet->ridges), ridge);
+ qh_setappend(&(neighbor->ridges), ridge);
+ numnew++;
+ }
+ }
+ }
+
+ trace2((qh ferr, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n",
+ numold, numnew));
+} /* mergecycle_ridges */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergecycle_vneighbors">-</a>
+
+ qh_mergecycle_vneighbors( samecycle, newfacet )
+ create vertex neighbors for newfacet from vertices of facets in samecycle
+ samecycle marked with visitid == qh.visit_id - 1
+
+ returns:
+ newfacet vertices with updated neighbors
+ marks newfacet with qh.visit_id-1
+ deletes vertices that are merged away
+ sets delridge on all vertices (faster here than in mergecycle_ridges)
+
+ see:
+ qh_mergevertex_neighbors()
+
+ design:
+ for each vertex of samecycle facet
+ set vertex->delridge
+ delete samecycle facets from vertex neighbors
+ append newfacet to vertex neighbors
+ if vertex only in newfacet
+ delete it from newfacet
+ add it to qh.del_vertices for later deletion
+*/
+void qh_mergecycle_vneighbors (facetT *samecycle, facetT *newfacet) {
+ facetT *neighbor, **neighborp;
+ unsigned int mergeid;
+ vertexT *vertex, **vertexp, *apex;
+ setT *vertices;
+
+ trace4((qh ferr, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));
+ mergeid= qh visit_id - 1;
+ newfacet->visitid= mergeid;
+ vertices= qh_basevertices (samecycle); /* temp */
+ apex= SETfirstt_(samecycle->vertices, vertexT);
+ qh_setappend (&vertices, apex);
+ FOREACHvertex_(vertices) {
+ vertex->delridge= True;
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid == mergeid)
+ SETref_(neighbor)= NULL;
+ }
+ qh_setcompact (vertex->neighbors);
+ qh_setappend (&vertex->neighbors, newfacet);
+ if (!SETsecond_(vertex->neighbors)) {
+ zinc_(Zcyclevertex);
+ trace2((qh ferr, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
+ vertex->id, samecycle->id, newfacet->id));
+ qh_setdelsorted (newfacet->vertices, vertex);
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+ }
+ }
+ qh_settempfree (&vertices);
+ trace3((qh ferr, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n",
+ samecycle->id, newfacet->id));
+} /* mergecycle_vneighbors */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergefacet">-</a>
+
+ qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
+ merges facet1 into facet2
+ mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
+
+ returns:
+ qh.max_outside and qh.min_vertex updated
+ initializes vertex neighbors on first merge
+
+ returns:
+ facet2 contains facet1's vertices, neighbors, and ridges
+ facet2 moved to end of qh.facet_list
+ makes facet2 a newfacet
+ sets facet2->newmerge set
+ clears facet2->center (unless merging into a large facet)
+ clears facet2->tested and ridge->tested for facet1
+
+ facet1 prepended to visible_list for later deletion and partitioning
+ facet1->f.replace == facet2
+
+ adds neighboring facets to facet_mergeset if redundant or degenerate
+
+ notes:
+ mindist/maxdist may be NULL
+ traces merge if fmax_(maxdist,-mindist) > TRACEdist
+
+ see:
+ qh_mergecycle()
+
+ design:
+ trace merge and check for degenerate simplex
+ make ridges for both facets
+ update qh.max_outside, qh.max_vertex, qh.min_vertex
+ update facet2->maxoutside and keepcentrum
+ update facet2->nummerge
+ update tested flags for facet2
+ if facet1 is simplicial
+ merge facet1 into facet2
+ else
+ merge facet1's neighbors into facet2
+ merge facet1's ridges into facet2
+ merge facet1's vertices into facet2
+ merge facet1's vertex neighbors into facet2
+ add facet2's vertices to qh.new_vertexlist
+ unless qh_MERGEapex
+ test facet2 for degenerate or redundant neighbors
+ move facet1 to qh.visible_list for later deletion
+ move facet2 to end of qh.newfacet_list
+*/
+void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
+ boolT traceonce= False;
+ vertexT *vertex, **vertexp;
+ int tracerestore=0, nummerge;
+
+ if (facet1->tricoplanar || facet2->tricoplanar) {
+ if (!qh TRInormals) {
+ fprintf (qh ferr, "qh_mergefacet: does not work for tricoplanar facets. Use option 'Q11'\n");
+ qh_errexit2 (qh_ERRqhull, facet1, facet2);
+ }
+ if (facet2->tricoplanar) {
+ facet2->tricoplanar= False;
+ facet2->keepcentrum= False;
+ }
+ }
+ zzinc_(Ztotmerge);
+ if (qh REPORTfreq2 && qh POSTmerging) {
+ if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+ qh_tracemerging();
+ }
+#ifndef qh_NOtrace
+ if (qh build_cnt >= qh RERUN) {
+ if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
+ tracerestore= 0;
+ qh IStracing= qh TRACElevel;
+ traceonce= True;
+ fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge #%d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
+ fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
+ }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
+ tracerestore= qh IStracing;
+ qh IStracing= 4;
+ traceonce= True;
+ fprintf (qh ferr, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
+ zzval_(Ztotmerge), qh tracefacet_id, qh furthest_id);
+ }
+ }
+ if (qh IStracing >= 2) {
+ realT mergemin= -2;
+ realT mergemax= -2;
+
+ if (mindist) {
+ mergemin= *mindist;
+ mergemax= *maxdist;
+ }
+ fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n",
+ zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
+ }
+#endif /* !qh_NOtrace */
+ if (facet1 == facet2 || facet1->visible || facet2->visible) {
+ fprintf (qh ferr, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
+ facet1->id, facet2->id);
+ qh_errexit2 (qh_ERRqhull, facet1, facet2);
+ }
+ if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
+ fprintf(qh ferr, "\n\
+qhull precision error: Only %d facets remain. Can not merge another\n\
+pair. The input is too degenerate or the convexity constraints are\n\
+too strong.\n", qh hull_dim+1);
+ if (qh hull_dim >= 5 && !qh MERGEexact)
+ fprintf(qh ferr, "Option 'Qx' may avoid this problem.\n");
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (!qh VERTEXneighbors)
+ qh_vertexneighbors();
+ qh_makeridges(facet1);
+ qh_makeridges(facet2);
+ if (qh IStracing >=4)
+ qh_errprint ("MERGING", facet1, facet2, NULL, NULL);
+ if (mindist) {
+ maximize_(qh max_outside, *maxdist);
+ maximize_(qh max_vertex, *maxdist);
+#if qh_MAXoutside
+ maximize_(facet2->maxoutside, *maxdist);
+#endif
+ minimize_(qh min_vertex, *mindist);
+ if (!facet2->keepcentrum
+ && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
+ facet2->keepcentrum= True;
+ zinc_(Zwidefacet);
+ }
+ }
+ nummerge= facet1->nummerge + facet2->nummerge + 1;
+ if (nummerge >= qh_MAXnummerge)
+ facet2->nummerge= qh_MAXnummerge;
+ else
+ facet2->nummerge= nummerge;
+ facet2->newmerge= True;
+ facet2->dupridge= False;
+ qh_updatetested (facet1, facet2);
+ if (qh hull_dim > 2 && qh_setsize (facet1->vertices) == qh hull_dim)
+ qh_mergesimplex (facet1, facet2, mergeapex);
+ else {
+ qh vertex_visit++;
+ FOREACHvertex_(facet2->vertices)
+ vertex->visitid= qh vertex_visit;
+ if (qh hull_dim == 2)
+ qh_mergefacet2d(facet1, facet2);
+ else {
+ qh_mergeneighbors(facet1, facet2);
+ qh_mergevertices(facet1->vertices, &facet2->vertices);
+ }
+ qh_mergeridges(facet1, facet2);
+ qh_mergevertex_neighbors(facet1, facet2);
+ if (!facet2->newfacet)
+ qh_newvertices (facet2->vertices);
+ }
+ if (!mergeapex)
+ qh_degen_redundant_neighbors (facet2, facet1);
+ if (facet2->coplanar || !facet2->newfacet) {
+ zinc_(Zmergeintohorizon);
+ }else if (!facet1->newfacet && facet2->newfacet) {
+ zinc_(Zmergehorizon);
+ }else {
+ zinc_(Zmergenew);
+ }
+ qh_willdelete (facet1, facet2);
+ qh_removefacet(facet2); /* append as a newfacet to end of qh facet_list */
+ qh_appendfacet(facet2);
+ facet2->newfacet= True;
+ facet2->tested= False;
+ qh_tracemerge (facet1, facet2);
+ if (traceonce) {
+ fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n");
+ qh IStracing= tracerestore;
+ }
+} /* mergefacet */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergefacet2d">-</a>
+
+ qh_mergefacet2d( facet1, facet2 )
+ in 2d, merges neighbors and vertices of facet1 into facet2
+
+ returns:
+ build ridges for neighbors if necessary
+ facet2 looks like a simplicial facet except for centrum, ridges
+ neighbors are opposite the corresponding vertex
+ maintains orientation of facet2
+
+ notes:
+ qh_mergefacet() retains non-simplicial structures
+ they are not needed in 2d, but later routines may use them
+ preserves qh.vertex_visit for qh_mergevertex_neighbors()
+
+ design:
+ get vertices and neighbors
+ determine new vertices and neighbors
+ set new vertices and neighbors and adjust orientation
+ make ridges for new neighbor if needed
+*/
+void qh_mergefacet2d (facetT *facet1, facetT *facet2) {
+ vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
+ facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
+
+ vertex1A= SETfirstt_(facet1->vertices, vertexT);
+ vertex1B= SETsecondt_(facet1->vertices, vertexT);
+ vertex2A= SETfirstt_(facet2->vertices, vertexT);
+ vertex2B= SETsecondt_(facet2->vertices, vertexT);
+ neighbor1A= SETfirstt_(facet1->neighbors, facetT);
+ neighbor1B= SETsecondt_(facet1->neighbors, facetT);
+ neighbor2A= SETfirstt_(facet2->neighbors, facetT);
+ neighbor2B= SETsecondt_(facet2->neighbors, facetT);
+ if (vertex1A == vertex2A) {
+ vertexA= vertex1B;
+ vertexB= vertex2B;
+ neighborA= neighbor2A;
+ neighborB= neighbor1A;
+ }else if (vertex1A == vertex2B) {
+ vertexA= vertex1B;
+ vertexB= vertex2A;
+ neighborA= neighbor2B;
+ neighborB= neighbor1A;
+ }else if (vertex1B == vertex2A) {
+ vertexA= vertex1A;
+ vertexB= vertex2B;
+ neighborA= neighbor2A;
+ neighborB= neighbor1B;
+ }else { /* 1B == 2B */
+ vertexA= vertex1A;
+ vertexB= vertex2A;
+ neighborA= neighbor2B;
+ neighborB= neighbor1B;
+ }
+ /* vertexB always from facet2, neighborB always from facet1 */
+ if (vertexA->id > vertexB->id) {
+ SETfirst_(facet2->vertices)= vertexA;
+ SETsecond_(facet2->vertices)= vertexB;
+ if (vertexB == vertex2A)
+ facet2->toporient= !facet2->toporient;
+ SETfirst_(facet2->neighbors)= neighborA;
+ SETsecond_(facet2->neighbors)= neighborB;
+ }else {
+ SETfirst_(facet2->vertices)= vertexB;
+ SETsecond_(facet2->vertices)= vertexA;
+ if (vertexB == vertex2B)
+ facet2->toporient= !facet2->toporient;
+ SETfirst_(facet2->neighbors)= neighborB;
+ SETsecond_(facet2->neighbors)= neighborA;
+ }
+ qh_makeridges (neighborB);
+ qh_setreplace(neighborB->neighbors, facet1, facet2);
+ trace4((qh ferr, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
+ vertexA->id, neighborB->id, facet1->id, facet2->id));
+} /* mergefacet2d */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergeneighbors">-</a>
+
+ qh_mergeneighbors( facet1, facet2 )
+ merges the neighbors of facet1 into facet2
+
+ see:
+ qh_mergecycle_neighbors()
+
+ design:
+ for each neighbor of facet1
+ if neighbor is also a neighbor of facet2
+ if neighbor is simpilicial
+ make ridges for later deletion as a degenerate facet
+ update its neighbor set
+ else
+ move the neighbor relation to facet2
+ remove the neighbor relation for facet1 and facet2
+*/
+void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
+ facetT *neighbor, **neighborp;
+
+ trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
+ facet1->id, facet2->id));
+ qh visit_id++;
+ FOREACHneighbor_(facet2) {
+ neighbor->visitid= qh visit_id;
+ }
+ FOREACHneighbor_(facet1) {
+ if (neighbor->visitid == qh visit_id) {
+ if (neighbor->simplicial) /* is degen, needs ridges */
+ qh_makeridges (neighbor);
+ if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
+ qh_setdel (neighbor->neighbors, facet1);
+ else {
+ qh_setdel(neighbor->neighbors, facet2);
+ qh_setreplace(neighbor->neighbors, facet1, facet2);
+ }
+ }else if (neighbor != facet2) {
+ qh_setappend(&(facet2->neighbors), neighbor);
+ qh_setreplace(neighbor->neighbors, facet1, facet2);
+ }
+ }
+ qh_setdel(facet1->neighbors, facet2); /* here for makeridges */
+ qh_setdel(facet2->neighbors, facet1);
+} /* mergeneighbors */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergeridges">-</a>
+
+ qh_mergeridges( facet1, facet2 )
+ merges the ridge set of facet1 into facet2
+
+ returns:
+ may delete all ridges for a vertex
+ sets vertex->delridge on deleted ridges
+
+ see:
+ qh_mergecycle_ridges()
+
+ design:
+ delete ridges between facet1 and facet2
+ mark (delridge) vertices on these ridges for later testing
+ for each remaining ridge
+ rename facet1 to facet2
+*/
+void qh_mergeridges(facetT *facet1, facetT *facet2) {
+ ridgeT *ridge, **ridgep;
+ vertexT *vertex, **vertexp;
+
+ trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n",
+ facet1->id, facet2->id));
+ FOREACHridge_(facet2->ridges) {
+ if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
+ FOREACHvertex_(ridge->vertices)
+ vertex->delridge= True;
+ qh_delridge(ridge); /* expensive in high-d, could rebuild */
+ ridgep--; /*repeat*/
+ }
+ }
+ FOREACHridge_(facet1->ridges) {
+ if (ridge->top == facet1)
+ ridge->top= facet2;
+ else
+ ridge->bottom= facet2;
+ qh_setappend(&(facet2->ridges), ridge);
+ }
+} /* mergeridges */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergesimplex">-</a>
+
+ qh_mergesimplex( facet1, facet2, mergeapex )
+ merge simplicial facet1 into facet2
+ mergeapex==qh_MERGEapex if merging samecycle into horizon facet
+ vertex id is latest (most recently created)
+ facet1 may be contained in facet2
+ ridges exist for both facets
+
+ returns:
+ facet2 with updated vertices, ridges, neighbors
+ updated neighbors for facet1's vertices
+ facet1 not deleted
+ sets vertex->delridge on deleted ridges
+
+ notes:
+ special case code since this is the most common merge
+ called from qh_mergefacet()
+
+ design:
+ if qh_MERGEapex
+ add vertices of facet2 to qh.new_vertexlist if necessary
+ add apex to facet2
+ else
+ for each ridge between facet1 and facet2
+ set vertex->delridge
+ determine the apex for facet1 (i.e., vertex to be merged)
+ unless apex already in facet2
+ insert apex into vertices for facet2
+ add vertices of facet2 to qh.new_vertexlist if necessary
+ add apex to qh.new_vertexlist if necessary
+ for each vertex of facet1
+ if apex
+ rename facet1 to facet2 in its vertex neighbors
+ else
+ delete facet1 from vertex neighors
+ if only in facet2
+ add vertex to qh.del_vertices for later deletion
+ for each ridge of facet1
+ delete ridges between facet1 and facet2
+ append other ridges to facet2 after renaming facet to facet2
+*/
+void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
+ vertexT *vertex, **vertexp, *apex;
+ ridgeT *ridge, **ridgep;
+ boolT issubset= False;
+ int vertex_i= -1, vertex_n;
+ facetT *neighbor, **neighborp, *otherfacet;
+
+ if (mergeapex) {
+ if (!facet2->newfacet)
+ qh_newvertices (facet2->vertices); /* apex is new */
+ apex= SETfirstt_(facet1->vertices, vertexT);
+ if (SETfirstt_(facet2->vertices, vertexT) != apex)
+ qh_setaddnth (&facet2->vertices, 0, apex); /* apex has last id */
+ else
+ issubset= True;
+ }else {
+ zinc_(Zmergesimplex);
+ FOREACHvertex_(facet1->vertices)
+ vertex->seen= False;
+ FOREACHridge_(facet1->ridges) {
+ if (otherfacet_(ridge, facet1) == facet2) {
+ FOREACHvertex_(ridge->vertices) {
+ vertex->seen= True;
+ vertex->delridge= True;
+ }
+ break;
+ }
+ }
+ FOREACHvertex_(facet1->vertices) {
+ if (!vertex->seen)
+ break; /* must occur */
+ }
+ apex= vertex;
+ trace4((qh ferr, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
+ apex->id, facet1->id, facet2->id));
+ FOREACHvertex_i_(facet2->vertices) {
+ if (vertex->id < apex->id) {
+ break;
+ }else if (vertex->id == apex->id) {
+ issubset= True;
+ break;
+ }
+ }
+ if (!issubset)
+ qh_setaddnth (&facet2->vertices, vertex_i, apex);
+ if (!facet2->newfacet)
+ qh_newvertices (facet2->vertices);
+ else if (!apex->newlist) {
+ qh_removevertex (apex);
+ qh_appendvertex (apex);
+ }
+ }
+ trace4((qh ferr, "qh_mergesimplex: update vertex neighbors of f%d\n",
+ facet1->id));
+ FOREACHvertex_(facet1->vertices) {
+ if (vertex == apex && !issubset)
+ qh_setreplace (vertex->neighbors, facet1, facet2);
+ else {
+ qh_setdel (vertex->neighbors, facet1);
+ if (!SETsecond_(vertex->neighbors))
+ qh_mergevertex_del (vertex, facet1, facet2);
+ }
+ }
+ trace4((qh ferr, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
+ facet1->id, facet2->id));
+ qh visit_id++;
+ FOREACHneighbor_(facet2)
+ neighbor->visitid= qh visit_id;
+ FOREACHridge_(facet1->ridges) {
+ otherfacet= otherfacet_(ridge, facet1);
+ if (otherfacet == facet2) {
+ qh_setdel (facet2->ridges, ridge);
+ qh_setfree(&(ridge->vertices));
+ qh_memfree (ridge, sizeof(ridgeT));
+ qh_setdel (facet2->neighbors, facet1);
+ }else {
+ qh_setappend (&facet2->ridges, ridge);
+ if (otherfacet->visitid != qh visit_id) {
+ qh_setappend (&facet2->neighbors, otherfacet);
+ qh_setreplace (otherfacet->neighbors, facet1, facet2);
+ otherfacet->visitid= qh visit_id;
+ }else {
+ if (otherfacet->simplicial) /* is degen, needs ridges */
+ qh_makeridges (otherfacet);
+ if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
+ qh_setdel (otherfacet->neighbors, facet1);
+ else { /*keep newfacet->neighbors->horizon*/
+ qh_setdel(otherfacet->neighbors, facet2);
+ qh_setreplace(otherfacet->neighbors, facet1, facet2);
+ }
+ }
+ if (ridge->top == facet1) /* wait until after qh_makeridges */
+ ridge->top= facet2;
+ else
+ ridge->bottom= facet2;
+ }
+ }
+ SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
+ trace3((qh ferr, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
+ facet1->id, getid_(apex), facet2->id));
+} /* mergesimplex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergevertex_del">-</a>
+
+ qh_mergevertex_del( vertex, facet1, facet2 )
+ delete a vertex because of merging facet1 into facet2
+
+ returns:
+ deletes vertex from facet2
+ adds vertex to qh.del_vertices for later deletion
+*/
+void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2) {
+
+ zinc_(Zmergevertex);
+ trace2((qh ferr, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
+ vertex->id, facet1->id, facet2->id));
+ qh_setdelsorted (facet2->vertices, vertex);
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+} /* mergevertex_del */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergevertex_neighbors">-</a>
+
+ qh_mergevertex_neighbors( facet1, facet2 )
+ merge the vertex neighbors of facet1 to facet2
+
+ returns:
+ if vertex is current qh.vertex_visit
+ deletes facet1 from vertex->neighbors
+ else
+ renames facet1 to facet2 in vertex->neighbors
+ deletes vertices if only one neighbor
+
+ notes:
+ assumes vertex neighbor sets are good
+*/
+void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
+ vertexT *vertex, **vertexp;
+
+ trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
+ facet1->id, facet2->id));
+ if (qh tracevertex) {
+ fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
+ facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
+ qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
+ }
+ FOREACHvertex_(facet1->vertices) {
+ if (vertex->visitid != qh vertex_visit)
+ qh_setreplace(vertex->neighbors, facet1, facet2);
+ else {
+ qh_setdel(vertex->neighbors, facet1);
+ if (!SETsecond_(vertex->neighbors))
+ qh_mergevertex_del (vertex, facet1, facet2);
+ }
+ }
+ if (qh tracevertex)
+ qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
+} /* mergevertex_neighbors */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="mergevertices">-</a>
+
+ qh_mergevertices( vertices1, vertices2 )
+ merges the vertex set of facet1 into facet2
+
+ returns:
+ replaces vertices2 with merged set
+ preserves vertex_visit for qh_mergevertex_neighbors
+ updates qh.newvertex_list
+
+ design:
+ create a merged set of both vertices (in inverse id order)
+*/
+void qh_mergevertices(setT *vertices1, setT **vertices2) {
+ int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
+ setT *mergedvertices;
+ vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
+
+ mergedvertices= qh_settemp (newsize);
+ FOREACHvertex_(vertices1) {
+ if (!*vertex2 || vertex->id > (*vertex2)->id)
+ qh_setappend (&mergedvertices, vertex);
+ else {
+ while (*vertex2 && (*vertex2)->id > vertex->id)
+ qh_setappend (&mergedvertices, *vertex2++);
+ if (!*vertex2 || (*vertex2)->id < vertex->id)
+ qh_setappend (&mergedvertices, vertex);
+ else
+ qh_setappend (&mergedvertices, *vertex2++);
+ }
+ }
+ while (*vertex2)
+ qh_setappend (&mergedvertices, *vertex2++);
+ if (newsize < qh_setsize (mergedvertices)) {
+ fprintf (qh ferr, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh_setfree(vertices2);
+ *vertices2= mergedvertices;
+ qh_settemppop ();
+} /* mergevertices */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="neighbor_intersections">-</a>
+
+ qh_neighbor_intersections( vertex )
+ return intersection of all vertices in vertex->neighbors except for vertex
+
+ returns:
+ returns temporary set of vertices
+ does not include vertex
+ NULL if a neighbor is simplicial
+ NULL if empty set
+
+ notes:
+ used for renaming vertices
+
+ design:
+ initialize the intersection set with vertices of the first two neighbors
+ delete vertex from the intersection
+ for each remaining neighbor
+ intersect its vertex set with the intersection set
+ return NULL if empty
+ return the intersection set
+*/
+setT *qh_neighbor_intersections (vertexT *vertex) {
+ facetT *neighbor, **neighborp, *neighborA, *neighborB;
+ setT *intersect;
+ int neighbor_i, neighbor_n;
+
+ FOREACHneighbor_(vertex) {
+ if (neighbor->simplicial)
+ return NULL;
+ }
+ neighborA= SETfirstt_(vertex->neighbors, facetT);
+ neighborB= SETsecondt_(vertex->neighbors, facetT);
+ zinc_(Zintersectnum);
+ if (!neighborA)
+ return NULL;
+ if (!neighborB)
+ intersect= qh_setcopy (neighborA->vertices, 0);
+ else
+ intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices);
+ qh_settemppush (intersect);
+ qh_setdelsorted (intersect, vertex);
+ FOREACHneighbor_i_(vertex) {
+ if (neighbor_i >= 2) {
+ zinc_(Zintersectnum);
+ qh_vertexintersect (&intersect, neighbor->vertices);
+ if (!SETfirst_(intersect)) {
+ zinc_(Zintersectfail);
+ qh_settempfree (&intersect);
+ return NULL;
+ }
+ }
+ }
+ trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
+ qh_setsize (intersect), vertex->id));
+ return intersect;
+} /* neighbor_intersections */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="newvertices">-</a>
+
+ qh_newvertices( vertices )
+ add vertices to end of qh.vertex_list (marks as new vertices)
+
+ returns:
+ vertices on qh.newvertex_list
+ vertex->newlist set
+*/
+void qh_newvertices (setT *vertices) {
+ vertexT *vertex, **vertexp;
+
+ FOREACHvertex_(vertices) {
+ if (!vertex->newlist) {
+ qh_removevertex (vertex);
+ qh_appendvertex (vertex);
+ }
+ }
+} /* newvertices */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="reducevertices">-</a>
+
+ qh_reducevertices()
+ reduce extra vertices, shared vertices, and redundant vertices
+ facet->newmerge is set if merged since last call
+ if !qh.MERGEvertices, only removes extra vertices
+
+ returns:
+ True if also merged degen_redundant facets
+ vertices are renamed if possible
+ clears facet->newmerge and vertex->delridge
+
+ notes:
+ ignored if 2-d
+
+ design:
+ merge any degenerate or redundant facets
+ for each newly merged facet
+ remove extra vertices
+ if qh.MERGEvertices
+ for each newly merged facet
+ for each vertex
+ if vertex was on a deleted ridge
+ rename vertex if it is shared
+ remove delridge flag from new vertices
+*/
+boolT qh_reducevertices (void) {
+ int numshare=0, numrename= 0;
+ boolT degenredun= False;
+ facetT *newfacet;
+ vertexT *vertex, **vertexp;
+
+ if (qh hull_dim == 2)
+ return False;
+ if (qh_merge_degenredundant())
+ degenredun= True;
+ LABELrestart:
+ FORALLnew_facets {
+ if (newfacet->newmerge) {
+ if (!qh MERGEvertices)
+ newfacet->newmerge= False;
+ qh_remove_extravertices (newfacet);
+ }
+ }
+ if (!qh MERGEvertices)
+ return False;
+ FORALLnew_facets {
+ if (newfacet->newmerge) {
+ newfacet->newmerge= False;
+ FOREACHvertex_(newfacet->vertices) {
+ if (vertex->delridge) {
+ if (qh_rename_sharedvertex (vertex, newfacet)) {
+ numshare++;
+ vertexp--; /* repeat since deleted vertex */
+ }
+ }
+ }
+ }
+ }
+ FORALLvertex_(qh newvertex_list) {
+ if (vertex->delridge && !vertex->deleted) {
+ vertex->delridge= False;
+ if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) {
+ numrename++;
+ if (qh_merge_degenredundant()) {
+ degenredun= True;
+ goto LABELrestart;
+ }
+ }
+ }
+ }
+ trace1((qh ferr, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
+ numshare, numrename, degenredun));
+ return degenredun;
+} /* reducevertices */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="redundant_vertex">-</a>
+
+ qh_redundant_vertex( vertex )
+ detect and rename a redundant vertex
+ vertices have full vertex->neighbors
+
+ returns:
+ returns true if find a redundant vertex
+ deletes vertex (vertex->deleted)
+
+ notes:
+ only needed if vertex->delridge and hull_dim >= 4
+ may add degenerate facets to qh.facet_mergeset
+ doesn't change vertex->neighbors or create redundant facets
+
+ design:
+ intersect vertices of all facet neighbors of vertex
+ determine ridges for these vertices
+ if find a new vertex for vertex amoung these ridges and vertices
+ rename vertex to the new vertex
+*/
+vertexT *qh_redundant_vertex (vertexT *vertex) {
+ vertexT *newvertex= NULL;
+ setT *vertices, *ridges;
+
+ trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));
+ if ((vertices= qh_neighbor_intersections (vertex))) {
+ ridges= qh_vertexridges (vertex);
+ if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
+ qh_renamevertex (vertex, newvertex, ridges, NULL, NULL);
+ qh_settempfree (&ridges);
+ qh_settempfree (&vertices);
+ }
+ return newvertex;
+} /* redundant_vertex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="remove_extravertices">-</a>
+
+ qh_remove_extravertices( facet )
+ remove extra vertices from non-simplicial facets
+
+ returns:
+ returns True if it finds them
+
+ design:
+ for each vertex in facet
+ if vertex not in a ridge (i.e., no longer used)
+ delete vertex from facet
+ delete facet from vertice's neighbors
+ unless vertex in another facet
+ add vertex to qh.del_vertices for later deletion
+*/
+boolT qh_remove_extravertices (facetT *facet) {
+ ridgeT *ridge, **ridgep;
+ vertexT *vertex, **vertexp;
+ boolT foundrem= False;
+
+ trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n",
+ facet->id));
+ FOREACHvertex_(facet->vertices)
+ vertex->seen= False;
+ FOREACHridge_(facet->ridges) {
+ FOREACHvertex_(ridge->vertices)
+ vertex->seen= True;
+ }
+ FOREACHvertex_(facet->vertices) {
+ if (!vertex->seen) {
+ foundrem= True;
+ zinc_(Zremvertex);
+ qh_setdelsorted (facet->vertices, vertex);
+ qh_setdel (vertex->neighbors, facet);
+ if (!qh_setsize (vertex->neighbors)) {
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+ zinc_(Zremvertexdel);
+ trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
+ }else
+ trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
+ vertexp--; /*repeat*/
+ }
+ }
+ return foundrem;
+} /* remove_extravertices */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="rename_sharedvertex">-</a>
+
+ qh_rename_sharedvertex( vertex, facet )
+ detect and rename if shared vertex in facet
+ vertices have full ->neighbors
+
+ returns:
+ newvertex or NULL
+ the vertex may still exist in other facets (i.e., a neighbor was pinched)
+ does not change facet->neighbors
+ updates vertex->neighbors
+
+ notes:
+ a shared vertex for a facet is only in ridges to one neighbor
+ this may undo a pinched facet
+
+ it does not catch pinches involving multiple facets. These appear
+ to be difficult to detect, since an exhaustive search is too expensive.
+
+ design:
+ if vertex only has two neighbors
+ determine the ridges that contain the vertex
+ determine the vertices shared by both neighbors
+ if can find a new vertex in this set
+ rename the vertex to the new vertex
+*/
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) {
+ facetT *neighbor, **neighborp, *neighborA= NULL;
+ setT *vertices, *ridges;
+ vertexT *newvertex;
+
+ if (qh_setsize (vertex->neighbors) == 2) {
+ neighborA= SETfirstt_(vertex->neighbors, facetT);
+ if (neighborA == facet)
+ neighborA= SETsecondt_(vertex->neighbors, facetT);
+ }else if (qh hull_dim == 3)
+ return NULL;
+ else {
+ qh visit_id++;
+ FOREACHneighbor_(facet)
+ neighbor->visitid= qh visit_id;
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visitid == qh visit_id) {
+ if (neighborA)
+ return NULL;
+ neighborA= neighbor;
+ }
+ }
+ if (!neighborA) {
+ fprintf (qh ferr, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
+ vertex->id, facet->id);
+ qh_errprint ("ERRONEOUS", facet, NULL, NULL, vertex);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ }
+ /* the vertex is shared by facet and neighborA */
+ ridges= qh_settemp (qh TEMPsize);
+ neighborA->visitid= ++qh visit_id;
+ qh_vertexridges_facet (vertex, facet, &ridges);
+ trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n",
+ qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id));
+ zinc_(Zintersectnum);
+ vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices);
+ qh_setdel (vertices, vertex);
+ qh_settemppush (vertices);
+ if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
+ qh_renamevertex (vertex, newvertex, ridges, facet, neighborA);
+ qh_settempfree (&vertices);
+ qh_settempfree (&ridges);
+ return newvertex;
+} /* rename_sharedvertex */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="renameridgevertex">-</a>
+
+ qh_renameridgevertex( ridge, oldvertex, newvertex )
+ renames oldvertex as newvertex in ridge
+
+ returns:
+
+ design:
+ delete oldvertex from ridge
+ if newvertex already in ridge
+ copy ridge->noconvex to another ridge if possible
+ delete the ridge
+ else
+ insert newvertex into the ridge
+ adjust the ridge's orientation
+*/
+void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
+ int nth= 0, oldnth;
+ facetT *temp;
+ vertexT *vertex, **vertexp;
+
+ oldnth= qh_setindex (ridge->vertices, oldvertex);
+ qh_setdelnthsorted (ridge->vertices, oldnth);
+ FOREACHvertex_(ridge->vertices) {
+ if (vertex == newvertex) {
+ zinc_(Zdelridge);
+ if (ridge->nonconvex) /* only one ridge has nonconvex set */
+ qh_copynonconvex (ridge);
+ qh_delridge (ridge);
+ trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted. It contained both v%d and v%d\n",
+ ridge->id, oldvertex->id, newvertex->id));
+ return;
+ }
+ if (vertex->id < newvertex->id)
+ break;
+ nth++;
+ }
+ qh_setaddnth(&ridge->vertices, nth, newvertex);
+ if (abs(oldnth - nth)%2) {
+ trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
+ ridge->id));
+ temp= ridge->top;
+ ridge->top= ridge->bottom;
+ ridge->bottom= temp;
+ }
+} /* renameridgevertex */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="renamevertex">-</a>
+
+ qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
+ renames oldvertex as newvertex in ridges
+ gives oldfacet/neighborA if oldvertex is shared between two facets
+
+ returns:
+ oldvertex may still exist afterwards
+
+
+ notes:
+ can not change neighbors of newvertex (since it's a subset)
+
+ design:
+ for each ridge in ridges
+ rename oldvertex to newvertex and delete degenerate ridges
+ if oldfacet not defined
+ for each neighbor of oldvertex
+ delete oldvertex from neighbor's vertices
+ remove extra vertices from neighbor
+ add oldvertex to qh.del_vertices
+ else if oldvertex only between oldfacet and neighborA
+ delete oldvertex from oldfacet and neighborA
+ add oldvertex to qh.del_vertices
+ else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
+ delete oldvertex from oldfacet
+ delete oldfacet from oldvertice's neighbors
+ remove extra vertices (e.g., oldvertex) from neighborA
+*/
+void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
+ facetT *neighbor, **neighborp;
+ ridgeT *ridge, **ridgep;
+ boolT istrace= False;
+
+ if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
+ newvertex->id == qh tracevertex_id)
+ istrace= True;
+ FOREACHridge_(ridges)
+ qh_renameridgevertex (ridge, oldvertex, newvertex);
+ if (!oldfacet) {
+ zinc_(Zrenameall);
+ if (istrace)
+ fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n",
+ oldvertex->id, newvertex->id);
+ FOREACHneighbor_(oldvertex) {
+ qh_maydropneighbor (neighbor);
+ qh_setdelsorted (neighbor->vertices, oldvertex);
+ if (qh_remove_extravertices (neighbor))
+ neighborp--; /* neighbor may be deleted */
+ }
+ if (!oldvertex->deleted) {
+ oldvertex->deleted= True;
+ qh_setappend (&qh del_vertices, oldvertex);
+ }
+ }else if (qh_setsize (oldvertex->neighbors) == 2) {
+ zinc_(Zrenameshare);
+ if (istrace)
+ fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n",
+ oldvertex->id, newvertex->id, oldfacet->id);
+ FOREACHneighbor_(oldvertex)
+ qh_setdelsorted (neighbor->vertices, oldvertex);
+ oldvertex->deleted= True;
+ qh_setappend (&qh del_vertices, oldvertex);
+ }else {
+ zinc_(Zrenamepinch);
+ if (istrace || qh IStracing)
+ fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n",
+ oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
+ qh_setdelsorted (oldfacet->vertices, oldvertex);
+ qh_setdel (oldvertex->neighbors, oldfacet);
+ qh_remove_extravertices (neighborA);
+ }
+} /* renamevertex */
+
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="test_appendmerge">-</a>
+
+ qh_test_appendmerge( facet, neighbor )
+ tests facet/neighbor for convexity
+ appends to mergeset if non-convex
+ if pre-merging,
+ nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
+
+ returns:
+ true if appends facet/neighbor to mergeset
+ sets facet->center as needed
+ does not change facet->seen
+
+ design:
+ if qh.cos_max is defined
+ if the angle between facet normals is too shallow
+ append an angle-coplanar merge to qh.mergeset
+ return True
+ make facet's centrum if needed
+ if facet's centrum is above the neighbor
+ set isconcave
+ else
+ if facet's centrum is not below the neighbor
+ set iscoplanar
+ make neighbor's centrum if needed
+ if neighbor's centrum is above the facet
+ set isconcave
+ else if neighbor's centrum is not below the facet
+ set iscoplanar
+ if isconcave or iscoplanar
+ get angle if needed
+ append concave or coplanar merge to qh.mergeset
+*/
+boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) {
+ realT dist, dist2= -REALmax, angle= -REALmax;
+ boolT isconcave= False, iscoplanar= False, okangle= False;
+
+ if (qh SKIPconvex && !qh POSTmerging)
+ return False;
+ if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
+ angle= qh_getangle(facet->normal, neighbor->normal);
+ zinc_(Zangletests);
+ if (angle > qh cos_max) {
+ zinc_(Zcoplanarangle);
+ qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
+ trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
+ angle, facet->id, neighbor->id));
+ return True;
+ }else
+ okangle= True;
+ }
+ if (!facet->center)
+ facet->center= qh_getcentrum (facet);
+ zzinc_(Zcentrumtests);
+ qh_distplane(facet->center, neighbor, &dist);
+ if (dist > qh centrum_radius)
+ isconcave= True;
+ else {
+ if (dist > -qh centrum_radius)
+ iscoplanar= True;
+ if (!neighbor->center)
+ neighbor->center= qh_getcentrum (neighbor);
+ zzinc_(Zcentrumtests);
+ qh_distplane(neighbor->center, facet, &dist2);
+ if (dist2 > qh centrum_radius)
+ isconcave= True;
+ else if (!iscoplanar && dist2 > -qh centrum_radius)
+ iscoplanar= True;
+ }
+ if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
+ return False;
+ if (!okangle && qh ANGLEmerge) {
+ angle= qh_getangle(facet->normal, neighbor->normal);
+ zinc_(Zangletests);
+ }
+ if (isconcave) {
+ zinc_(Zconcaveridge);
+ if (qh ANGLEmerge)
+ angle += qh_ANGLEconcave + 0.5;
+ qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
+ trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
+ facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
+ }else /* iscoplanar */ {
+ zinc_(Zcoplanarcentrum);
+ qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
+ trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
+ facet->id, neighbor->id, dist, dist2, angle));
+ }
+ return True;
+} /* test_appendmerge */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="test_vneighbors">-</a>
+
+ qh_test_vneighbors()
+ test vertex neighbors for convexity
+ tests all facets on qh.newfacet_list
+
+ returns:
+ true if non-convex vneighbors appended to qh.facet_mergeset
+ initializes vertex neighbors if needed
+
+ notes:
+ assumes all facet neighbors have been tested
+ this can be expensive
+ this does not guarantee that a centrum is below all facets
+ but it is unlikely
+ uses qh.visit_id
+
+ design:
+ build vertex neighbors if necessary
+ for all new facets
+ for all vertices
+ for each unvisited facet neighbor of the vertex
+ test new facet and neighbor for convexity
+*/
+boolT qh_test_vneighbors (void /* qh newfacet_list */) {
+ facetT *newfacet, *neighbor, **neighborp;
+ vertexT *vertex, **vertexp;
+ int nummerges= 0;
+
+ trace1((qh ferr, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
+ if (!qh VERTEXneighbors)
+ qh_vertexneighbors();
+ FORALLnew_facets
+ newfacet->seen= False;
+ FORALLnew_facets {
+ newfacet->seen= True;
+ newfacet->visitid= qh visit_id++;
+ FOREACHneighbor_(newfacet)
+ newfacet->visitid= qh visit_id;
+ FOREACHvertex_(newfacet->vertices) {
+ FOREACHneighbor_(vertex) {
+ if (neighbor->seen || neighbor->visitid == qh visit_id)
+ continue;
+ if (qh_test_appendmerge (newfacet, neighbor))
+ nummerges++;
+ }
+ }
+ }
+ zadd_(Ztestvneighbor, nummerges);
+ trace1((qh ferr, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
+ nummerges));
+ return (nummerges > 0);
+} /* test_vneighbors */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="tracemerge">-</a>
+
+ qh_tracemerge( facet1, facet2 )
+ print trace message after merge
+*/
+void qh_tracemerge (facetT *facet1, facetT *facet2) {
+ boolT waserror= False;
+
+#ifndef qh_NOtrace
+ if (qh IStracing >= 4)
+ qh_errprint ("MERGED", facet2, NULL, NULL, NULL);
+ if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
+ fprintf (qh ferr, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
+ if (facet2 != qh tracefacet)
+ qh_errprint ("TRACE", qh tracefacet,
+ (qh tracevertex && qh tracevertex->neighbors) ?
+ SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
+ NULL, qh tracevertex);
+ }
+ if (qh tracevertex) {
+ if (qh tracevertex->deleted)
+ fprintf (qh ferr, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
+ qh furthest_id);
+ else
+ qh_checkvertex (qh tracevertex);
+ }
+ if (qh tracefacet) {
+ qh_checkfacet (qh tracefacet, True, &waserror);
+ if (waserror)
+ qh_errexit (qh_ERRqhull, qh tracefacet, NULL);
+ }
+#endif /* !qh_NOtrace */
+ if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
+ qh_checkfacet (facet2, True, &waserror);
+ if (waserror)
+ qh_errexit(qh_ERRqhull, NULL, NULL);
+ }
+} /* tracemerge */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="tracemerging">-</a>
+
+ qh_tracemerging()
+ print trace message during POSTmerging
+
+ returns:
+ updates qh.mergereport
+
+ notes:
+ called from qh_mergecycle() and qh_mergefacet()
+
+ see:
+ qh_buildtracing()
+*/
+void qh_tracemerging (void) {
+ realT cpu;
+ int total;
+ time_t timedata;
+ struct tm *tp;
+
+ qh mergereport= zzval_(Ztotmerge);
+ time (&timedata);
+ tp= localtime (&timedata);
+ cpu= qh_CPUclock;
+ cpu /= qh_SECticks;
+ total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+ fprintf (qh ferr, "\n\
+At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets. The hull\n\
+ contains %d facets and %d vertices.\n",
+ tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
+ total, qh num_facets - qh num_visible,
+ qh num_vertices-qh_setsize (qh del_vertices));
+} /* tracemerging */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="updatetested">-</a>
+
+ qh_updatetested( facet1, facet2 )
+ clear facet2->tested and facet1->ridge->tested for merge
+
+ returns:
+ deletes facet2->center unless it's already large
+ if so, clears facet2->ridge->tested
+
+ design:
+ clear facet2->tested
+ clear ridge->tested for facet1's ridges
+ if facet2 has a centrum
+ if facet2 is large
+ set facet2->keepcentrum
+ else if facet2 has 3 vertices due to many merges, or not large and post merging
+ clear facet2->keepcentrum
+ unless facet2->keepcentrum
+ clear facet2->center to recompute centrum later
+ clear ridge->tested for facet2's ridges
+*/
+void qh_updatetested (facetT *facet1, facetT *facet2) {
+ ridgeT *ridge, **ridgep;
+ int size;
+
+ facet2->tested= False;
+ FOREACHridge_(facet1->ridges)
+ ridge->tested= False;
+ if (!facet2->center)
+ return;
+ size= qh_setsize (facet2->vertices);
+ if (!facet2->keepcentrum) {
+ if (size > qh hull_dim + qh_MAXnewcentrum) {
+ facet2->keepcentrum= True;
+ zinc_(Zwidevertices);
+ }
+ }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
+ /* center and keepcentrum was set */
+ if (size == qh hull_dim || qh POSTmerging)
+ facet2->keepcentrum= False; /* if many merges need to recompute centrum */
+ }
+ if (!facet2->keepcentrum) {
+ qh_memfree (facet2->center, qh normal_size);
+ facet2->center= NULL;
+ FOREACHridge_(facet2->ridges)
+ ridge->tested= False;
+ }
+} /* updatetested */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="vertexridges">-</a>
+
+ qh_vertexridges( vertex )
+ return temporary set of ridges adjacent to a vertex
+ vertex->neighbors defined
+
+ ntoes:
+ uses qh.visit_id
+ does not include implicit ridges for simplicial facets
+
+ design:
+ for each neighbor of vertex
+ add ridges that include the vertex to ridges
+*/
+setT *qh_vertexridges (vertexT *vertex) {
+ facetT *neighbor, **neighborp;
+ setT *ridges= qh_settemp (qh TEMPsize);
+ int size;
+
+ qh visit_id++;
+ FOREACHneighbor_(vertex)
+ neighbor->visitid= qh visit_id;
+ FOREACHneighbor_(vertex) {
+ if (*neighborp) /* no new ridges in last neighbor */
+ qh_vertexridges_facet (vertex, neighbor, &ridges);
+ }
+ if (qh PRINTstatistics || qh IStracing) {
+ size= qh_setsize (ridges);
+ zinc_(Zvertexridge);
+ zadd_(Zvertexridgetot, size);
+ zmax_(Zvertexridgemax, size);
+ trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n",
+ size, vertex->id));
+ }
+ return ridges;
+} /* vertexridges */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="vertexridges_facet">-</a>
+
+ qh_vertexridges_facet( vertex, facet, ridges )
+ add adjacent ridges for vertex in facet
+ neighbor->visitid==qh.visit_id if it hasn't been visited
+
+ returns:
+ ridges updated
+ sets facet->visitid to qh.visit_id-1
+
+ design:
+ for each ridge of facet
+ if ridge of visited neighbor (i.e., unprocessed)
+ if vertex in ridge
+ append ridge to vertex
+ mark facet processed
+*/
+void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) {
+ ridgeT *ridge, **ridgep;
+ facetT *neighbor;
+
+ FOREACHridge_(facet->ridges) {
+ neighbor= otherfacet_(ridge, facet);
+ if (neighbor->visitid == qh visit_id
+ && qh_setin (ridge->vertices, vertex))
+ qh_setappend (ridges, ridge);
+ }
+ facet->visitid= qh visit_id-1;
+} /* vertexridges_facet */
+
+/*-<a href="qh-merge.htm#TOC"
+ >-------------------------------</a><a name="willdelete">-</a>
+
+ qh_willdelete( facet, replace )
+ moves facet to visible list
+ sets facet->f.replace to replace (may be NULL)
+
+ returns:
+ bumps qh.num_visible
+*/
+void qh_willdelete (facetT *facet, facetT *replace) {
+
+ qh_removefacet(facet);
+ qh_prependfacet (facet, &qh visible_list);
+ qh num_visible++;
+ facet->visible= True;
+ facet->f.replace= replace;
+} /* willdelete */
+
+#else /* qh_NOmerge */
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
+}
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle,
+ boolT vneighbors) {
+}
+boolT qh_checkzero (boolT testall) {
+ }
+#endif /* qh_NOmerge */
+
diff --git a/extern/qhull/src/merge.h b/extern/qhull/src/merge.h
new file mode 100644
index 00000000000..7fc2afa5967
--- /dev/null
+++ b/extern/qhull/src/merge.h
@@ -0,0 +1,171 @@
+/*<html><pre> -<a href="qh-merge.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ merge.h
+ header file for merge.c
+
+ see qh-merge.htm and merge.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+
+/*============ -constants- ==============*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEredundant">-</a>
+
+ qh_ANGLEredundant
+ indicates redundant merge in mergeT->angle
+*/
+#define qh_ANGLEredundant 6.0
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEdegen">-</a>
+
+ qh_ANGLEdegen
+ indicates degenerate facet in mergeT->angle
+*/
+#define qh_ANGLEdegen 5.0
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_ANGLEconcave">-</a>
+
+ qh_ANGLEconcave
+ offset to indicate concave facets in mergeT->angle
+
+ notes:
+ concave facets are assigned the range of [2,4] in mergeT->angle
+ roundoff error may make the angle less than 2
+*/
+#define qh_ANGLEconcave 1.5
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="MRG">-</a>
+
+ MRG... (mergeType)
+ indicates the type of a merge (mergeT->type)
+*/
+typedef enum { /* in sort order for facet_mergeset */
+ MRGnone= 0,
+ MRGcoplanar, /* centrum coplanar */
+ MRGanglecoplanar, /* angle coplanar */
+ /* could detect half concave ridges */
+ MRGconcave, /* concave ridge */
+ MRGflip, /* flipped facet. facet1 == facet2 */
+ MRGridge, /* duplicate ridge (qh_MERGEridge) */
+ /* degen and redundant go onto degen_mergeset */
+ MRGdegen, /* degenerate facet (not enough neighbors) facet1 == facet2 */
+ MRGredundant, /* redundant facet (vertex subset) */
+ /* merge_degenredundant assumes degen < redundant */
+ MRGmirror, /* mirror facet from qh_triangulate */
+ ENDmrg
+} mergeType;
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="qh_MERGEapex">-</a>
+
+ qh_MERGEapex
+ flag for qh_mergefacet() to indicate an apex merge
+*/
+#define qh_MERGEapex True
+
+/*============ -structures- ====================*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="mergeT">-</a>
+
+ mergeT
+ structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT { /* initialize in qh_appendmergeset */
+ realT angle; /* angle between normals of facet1 and facet2 */
+ facetT *facet1; /* will merge facet1 into facet2 */
+ facetT *facet2;
+ mergeType type;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-merge.htm#TOC"
+ >--------------------------------</a><a name="FOREACHmerge_">-</a>
+
+ FOREACHmerge_( merges ) {...}
+ assign 'merge' to each merge in merges
+
+ notes:
+ uses 'mergeT *merge, **mergep;'
+ if qh_mergefacet(),
+ restart since qh.facet_mergeset may change
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle,
+ boolT vneighbors);
+void qh_all_merges (boolT othermerge, boolT vneighbors);
+void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
+setT *qh_basevertices( facetT *samecycle);
+void qh_checkconnect (void /* qh new_facets */);
+boolT qh_checkzero (boolT testall);
+void qh_copynonconvex (ridgeT *atridge);
+void qh_degen_redundant_facet (facetT *facet);
+void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
+void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+ facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
+void qh_forcedmerges( boolT *wasmerge);
+void qh_getmergeset(facetT *facetlist);
+void qh_getmergeset_initial (facetT *facetlist);
+void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge,
+ vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void qh_makeridges(facetT *facet);
+void qh_mark_dupridges(facetT *facetlist);
+void qh_maydropneighbor (facetT *facet);
+int qh_merge_degenredundant (void);
+void qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
+void qh_mergecycle (facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
+void qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
+void qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
+void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
+void qh_mergefacet2d (facetT *facet1, facetT *facet2);
+void qh_mergeneighbors(facetT *facet1, facetT *facet2);
+void qh_mergeridges(facetT *facet1, facetT *facet2);
+void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
+void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
+void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
+void qh_mergevertices(setT *vertices1, setT **vertices);
+setT *qh_neighbor_intersections (vertexT *vertex);
+void qh_newvertices (setT *vertices);
+boolT qh_reducevertices (void);
+vertexT *qh_redundant_vertex (vertexT *vertex);
+boolT qh_remove_extravertices (facetT *facet);
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
+void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+ facetT *oldfacet, facetT *neighborA);
+boolT qh_test_appendmerge (facetT *facet, facetT *neighbor);
+boolT qh_test_vneighbors (void /* qh newfacet_list */);
+void qh_tracemerge (facetT *facet1, facetT *facet2);
+void qh_tracemerging (void);
+void qh_updatetested( facetT *facet1, facetT *facet2);
+setT *qh_vertexridges (vertexT *vertex);
+void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
+void qh_willdelete (facetT *facet, facetT *replace);
+
+#endif /* qhDEFmerge */
diff --git a/extern/qhull/src/poly.c b/extern/qhull/src/poly.c
new file mode 100644
index 00000000000..6319e43d66a
--- /dev/null
+++ b/extern/qhull/src/poly.c
@@ -0,0 +1,1180 @@
+/*<html><pre> -<a href="qh-poly.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ poly.c
+ implements polygons and simplices
+
+ see qh-poly.htm, poly.h and qhull.h
+
+ infrequent code is in poly2.c
+ (all but top 50 and their callers 12/3/95)
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="appendfacet">-</a>
+
+ qh_appendfacet( facet )
+ appends facet to end of qh.facet_list,
+
+ returns:
+ updates qh.newfacet_list, facet_next, facet_list
+ increments qh.numfacets
+
+ notes:
+ assumes qh.facet_list/facet_tail is defined (createsimplex)
+
+ see:
+ qh_removefacet()
+
+*/
+void qh_appendfacet(facetT *facet) {
+ facetT *tail= qh facet_tail;
+
+ if (tail == qh newfacet_list)
+ qh newfacet_list= facet;
+ if (tail == qh facet_next)
+ qh facet_next= facet;
+ facet->previous= tail->previous;
+ facet->next= tail;
+ if (tail->previous)
+ tail->previous->next= facet;
+ else
+ qh facet_list= facet;
+ tail->previous= facet;
+ qh num_facets++;
+ trace4((qh ferr, "qh_appendfacet: append f%d to facet_list\n", facet->id));
+} /* appendfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="appendvertex">-</a>
+
+ qh_appendvertex( vertex )
+ appends vertex to end of qh.vertex_list,
+
+ returns:
+ sets vertex->newlist
+ updates qh.vertex_list, newvertex_list
+ increments qh.num_vertices
+
+ notes:
+ assumes qh.vertex_list/vertex_tail is defined (createsimplex)
+
+*/
+void qh_appendvertex (vertexT *vertex) {
+ vertexT *tail= qh vertex_tail;
+
+ if (tail == qh newvertex_list)
+ qh newvertex_list= vertex;
+ vertex->newlist= True;
+ vertex->previous= tail->previous;
+ vertex->next= tail;
+ if (tail->previous)
+ tail->previous->next= vertex;
+ else
+ qh vertex_list= vertex;
+ tail->previous= vertex;
+ qh num_vertices++;
+ trace4((qh ferr, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
+} /* appendvertex */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="attachnewfacets">-</a>
+
+ qh_attachnewfacets( )
+ attach horizon facets to new facets in qh.newfacet_list
+ newfacets have neighbor and ridge links to horizon but not vice versa
+ only needed for qh.ONLYgood
+
+ returns:
+ set qh.NEWfacets
+ horizon facets linked to new facets
+ ridges changed from visible facets to new facets
+ simplicial ridges deleted
+ qh.visible_list, no ridges valid
+ facet->f.replace is a newfacet (if any)
+
+ design:
+ delete interior ridges and neighbor sets by
+ for each visible, non-simplicial facet
+ for each ridge
+ if last visit or if neighbor is simplicial
+ if horizon neighbor
+ delete ridge for horizon's ridge set
+ delete ridge
+ erase neighbor set
+ attach horizon facets and new facets by
+ for all new facets
+ if corresponding horizon facet is simplicial
+ locate corresponding visible facet {may be more than one}
+ link visible facet to new facet
+ replace visible facet with new facet in horizon
+ else it's non-simplicial
+ for all visible neighbors of the horizon facet
+ link visible neighbor to new facet
+ delete visible neighbor from horizon facet
+ append new facet to horizon's neighbors
+ the first ridge of the new facet is the horizon ridge
+ link the new facet into the horizon ridge
+*/
+void qh_attachnewfacets (void ) {
+ facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
+ ridgeT *ridge, **ridgep;
+
+ qh NEWfacets= True;
+ trace3((qh ferr, "qh_attachnewfacets: delete interior ridges\n"));
+ qh visit_id++;
+ FORALLvisible_facets {
+ visible->visitid= qh visit_id;
+ if (visible->ridges) {
+ FOREACHridge_(visible->ridges) {
+ neighbor= otherfacet_(ridge, visible);
+ if (neighbor->visitid == qh visit_id
+ || (!neighbor->visible && neighbor->simplicial)) {
+ if (!neighbor->visible) /* delete ridge for simplicial horizon */
+ qh_setdel (neighbor->ridges, ridge);
+ qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */
+ qh_memfree (ridge, sizeof(ridgeT));
+ }
+ }
+ SETfirst_(visible->ridges)= NULL;
+ }
+ SETfirst_(visible->neighbors)= NULL;
+ }
+ trace1((qh ferr, "qh_attachnewfacets: attach horizon facets to new facets\n"));
+ FORALLnew_facets {
+ horizon= SETfirstt_(newfacet->neighbors, facetT);
+ if (horizon->simplicial) {
+ visible= NULL;
+ FOREACHneighbor_(horizon) { /* may have more than one horizon ridge */
+ if (neighbor->visible) {
+ if (visible) {
+ if (qh_setequal_skip (newfacet->vertices, 0, horizon->vertices,
+ SETindex_(horizon->neighbors, neighbor))) {
+ visible= neighbor;
+ break;
+ }
+ }else
+ visible= neighbor;
+ }
+ }
+ if (visible) {
+ visible->f.replace= newfacet;
+ qh_setreplace (horizon->neighbors, visible, newfacet);
+ }else {
+ fprintf (qh ferr, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
+ horizon->id, newfacet->id);
+ qh_errexit2 (qh_ERRqhull, horizon, newfacet);
+ }
+ }else { /* non-simplicial, with a ridge for newfacet */
+ FOREACHneighbor_(horizon) { /* may hold for many new facets */
+ if (neighbor->visible) {
+ neighbor->f.replace= newfacet;
+ qh_setdelnth (horizon->neighbors,
+ SETindex_(horizon->neighbors, neighbor));
+ neighborp--; /* repeat */
+ }
+ }
+ qh_setappend (&horizon->neighbors, newfacet);
+ ridge= SETfirstt_(newfacet->ridges, ridgeT);
+ if (ridge->top == horizon)
+ ridge->bottom= newfacet;
+ else
+ ridge->top= newfacet;
+ }
+ } /* newfacets */
+ if (qh PRINTstatistics) {
+ FORALLvisible_facets {
+ if (!visible->f.replace)
+ zinc_(Zinsidevisible);
+ }
+ }
+} /* attachnewfacets */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkflipped">-</a>
+
+ qh_checkflipped( facet, dist, allerror )
+ checks facet orientation to interior point
+
+ if allerror set,
+ tests against qh.DISTround
+ else
+ tests against 0 since tested against DISTround before
+
+ returns:
+ False if it flipped orientation (sets facet->flipped)
+ distance if non-NULL
+*/
+boolT qh_checkflipped (facetT *facet, realT *distp, boolT allerror) {
+ realT dist;
+
+ if (facet->flipped && !distp)
+ return False;
+ zzinc_(Zdistcheck);
+ qh_distplane(qh interior_point, facet, &dist);
+ if (distp)
+ *distp= dist;
+ if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
+ facet->flipped= True;
+ zzinc_(Zflippedfacets);
+ trace0((qh ferr, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
+ facet->id, dist, qh furthest_id));
+ qh_precision ("flipped facet");
+ return False;
+ }
+ return True;
+} /* checkflipped */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="delfacet">-</a>
+
+ qh_delfacet( facet )
+ removes facet from facet_list and frees up its memory
+
+ notes:
+ assumes vertices and ridges already freed
+*/
+void qh_delfacet(facetT *facet) {
+ void **freelistp; /* used !qh_NOmem */
+
+ trace4((qh ferr, "qh_delfacet: delete f%d\n", facet->id));
+ if (facet == qh tracefacet)
+ qh tracefacet= NULL;
+ if (facet == qh GOODclosest)
+ qh GOODclosest= NULL;
+ qh_removefacet(facet);
+ if (!facet->tricoplanar || facet->keepcentrum) {
+ qh_memfree_(facet->normal, qh normal_size, freelistp);
+ if (qh CENTERtype == qh_ASvoronoi) { /* uses macro calls */
+ qh_memfree_(facet->center, qh center_size, freelistp);
+ }else /* AScentrum */ {
+ qh_memfree_(facet->center, qh normal_size, freelistp);
+ }
+ }
+ qh_setfree(&(facet->neighbors));
+ if (facet->ridges)
+ qh_setfree(&(facet->ridges));
+ qh_setfree(&(facet->vertices));
+ if (facet->outsideset)
+ qh_setfree(&(facet->outsideset));
+ if (facet->coplanarset)
+ qh_setfree(&(facet->coplanarset));
+ qh_memfree_(facet, sizeof(facetT), freelistp);
+} /* delfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="deletevisible">-</a>
+
+ qh_deletevisible()
+ delete visible facets and vertices
+
+ returns:
+ deletes each facet and removes from facetlist
+ at exit, qh.visible_list empty (== qh.newfacet_list)
+
+ notes:
+ ridges already deleted
+ horizon facets do not reference facets on qh.visible_list
+ new facets in qh.newfacet_list
+ uses qh.visit_id;
+*/
+void qh_deletevisible (void /*qh visible_list*/) {
+ facetT *visible, *nextfacet;
+ vertexT *vertex, **vertexp;
+ int numvisible= 0, numdel= qh_setsize(qh del_vertices);
+
+ trace1((qh ferr, "qh_deletevisible: delete %d visible facets and %d vertices\n",
+ qh num_visible, numdel));
+ for (visible= qh visible_list; visible && visible->visible;
+ visible= nextfacet) { /* deleting current */
+ nextfacet= visible->next;
+ numvisible++;
+ qh_delfacet(visible);
+ }
+ if (numvisible != qh num_visible) {
+ fprintf (qh ferr, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
+ qh num_visible, numvisible);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh num_visible= 0;
+ zadd_(Zvisfacettot, numvisible);
+ zmax_(Zvisfacetmax, numvisible);
+ zzadd_(Zdelvertextot, numdel);
+ zmax_(Zdelvertexmax, numdel);
+ FOREACHvertex_(qh del_vertices)
+ qh_delvertex (vertex);
+ qh_settruncate (qh del_vertices, 0);
+} /* deletevisible */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="facetintersect">-</a>
+
+ qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
+ return vertices for intersection of two simplicial facets
+ may include 1 prepended entry (if more, need to settemppush)
+
+ returns:
+ returns set of qh.hull_dim-1 + prepend vertices
+ returns skipped index for each test and checks for exactly one
+
+ notes:
+ does not need settemp since set in quick memory
+
+ see also:
+ qh_vertexintersect and qh_vertexintersect_new
+ use qh_setnew_delnthsorted to get nth ridge (no skip information)
+
+ design:
+ locate skipped vertex by scanning facet A's neighbors
+ locate skipped vertex by scanning facet B's neighbors
+ intersect the vertex sets
+*/
+setT *qh_facetintersect (facetT *facetA, facetT *facetB,
+ int *skipA,int *skipB, int prepend) {
+ setT *intersect;
+ int dim= qh hull_dim, i, j;
+ facetT **neighborsA, **neighborsB;
+
+ neighborsA= SETaddr_(facetA->neighbors, facetT);
+ neighborsB= SETaddr_(facetB->neighbors, facetT);
+ i= j= 0;
+ if (facetB == *neighborsA++)
+ *skipA= 0;
+ else if (facetB == *neighborsA++)
+ *skipA= 1;
+ else if (facetB == *neighborsA++)
+ *skipA= 2;
+ else {
+ for (i= 3; i < dim; i++) {
+ if (facetB == *neighborsA++) {
+ *skipA= i;
+ break;
+ }
+ }
+ }
+ if (facetA == *neighborsB++)
+ *skipB= 0;
+ else if (facetA == *neighborsB++)
+ *skipB= 1;
+ else if (facetA == *neighborsB++)
+ *skipB= 2;
+ else {
+ for (j= 3; j < dim; j++) {
+ if (facetA == *neighborsB++) {
+ *skipB= j;
+ break;
+ }
+ }
+ }
+ if (i >= dim || j >= dim) {
+ fprintf (qh ferr, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
+ facetA->id, facetB->id);
+ qh_errexit2 (qh_ERRqhull, facetA, facetB);
+ }
+ intersect= qh_setnew_delnthsorted (facetA->vertices, qh hull_dim, *skipA, prepend);
+ trace4((qh ferr, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
+ facetA->id, *skipA, facetB->id, *skipB));
+ return(intersect);
+} /* facetintersect */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="gethash">-</a>
+
+ qh_gethash( hashsize, set, size, firstindex, skipelem )
+ return hashvalue for a set with firstindex and skipelem
+
+ notes:
+ assumes at least firstindex+1 elements
+ assumes skipelem is NULL, in set, or part of hash
+
+ hashes memory addresses which may change over different runs of the same data
+ using sum for hash does badly in high d
+*/
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem) {
+ void **elemp= SETelemaddr_(set, firstindex, void);
+ ptr_intT hash = 0, elem;
+ int i;
+
+ switch (size-firstindex) {
+ case 1:
+ hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
+ break;
+ case 2:
+ hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
+ break;
+ case 3:
+ hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+ - (ptr_intT) skipelem;
+ break;
+ case 4:
+ hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+ + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
+ break;
+ case 5:
+ hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+ + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
+ break;
+ case 6:
+ hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+ + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
+ - (ptr_intT) skipelem;
+ break;
+ default:
+ hash= 0;
+ i= 3;
+ do { /* this is about 10% in 10-d */
+ if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
+ hash ^= (elem << i) + (elem >> (32-i));
+ i += 3;
+ if (i >= 32)
+ i -= 32;
+ }
+ }while(*elemp);
+ break;
+ }
+ hash %= (ptr_intT) hashsize;
+ /* hash= 0; for debugging purposes */
+ return hash;
+} /* gethash */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="makenewfacet">-</a>
+
+ qh_makenewfacet( vertices, toporient, horizon )
+ creates a toporient? facet from vertices
+
+ returns:
+ returns newfacet
+ adds newfacet to qh.facet_list
+ newfacet->vertices= vertices
+ if horizon
+ newfacet->neighbor= horizon, but not vice versa
+ newvertex_list updated with vertices
+*/
+facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
+ facetT *newfacet;
+ vertexT *vertex, **vertexp;
+
+ FOREACHvertex_(vertices) {
+ if (!vertex->newlist) {
+ qh_removevertex (vertex);
+ qh_appendvertex (vertex);
+ }
+ }
+ newfacet= qh_newfacet();
+ newfacet->vertices= vertices;
+ newfacet->toporient= toporient;
+ if (horizon)
+ qh_setappend(&(newfacet->neighbors), horizon);
+ qh_appendfacet(newfacet);
+ return(newfacet);
+} /* makenewfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="makenewplanes">-</a>
+
+ qh_makenewplanes()
+ make new hyperplanes for facets on qh.newfacet_list
+
+ returns:
+ all facets have hyperplanes or are marked for merging
+ doesn't create hyperplane if horizon is coplanar (will merge)
+ updates qh.min_vertex if qh.JOGGLEmax
+
+ notes:
+ facet->f.samecycle is defined for facet->mergehorizon facets
+*/
+void qh_makenewplanes (void /* newfacet_list */) {
+ facetT *newfacet;
+
+ FORALLnew_facets {
+ if (!newfacet->mergehorizon)
+ qh_setfacetplane (newfacet);
+ }
+ if (qh JOGGLEmax < REALmax/2)
+ minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
+} /* makenewplanes */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
+
+ qh_makenew_nonsimplicial( visible, apex, numnew )
+ make new facets for ridges of a visible facet
+
+ returns:
+ first newfacet, bumps numnew as needed
+ attaches new facets if !qh.ONLYgood
+ marks ridge neighbors for simplicial visible
+ if (qh.ONLYgood)
+ ridges on newfacet, horizon, and visible
+ else
+ ridge and neighbors between newfacet and horizon
+ visible facet's ridges are deleted
+
+ notes:
+ qh.visit_id if visible has already been processed
+ sets neighbor->seen for building f.samecycle
+ assumes all 'seen' flags initially false
+
+ design:
+ for each ridge of visible facet
+ get neighbor of visible facet
+ if neighbor was already processed
+ delete the ridge (will delete all visible facets later)
+ if neighbor is a horizon facet
+ create a new facet
+ if neighbor coplanar
+ adds newfacet to f.samecycle for later merging
+ else
+ updates neighbor's neighbor set
+ (checks for non-simplicial facet with multiple ridges to visible facet)
+ updates neighbor's ridge set
+ (checks for simplicial neighbor to non-simplicial visible facet)
+ (deletes ridge if neighbor is simplicial)
+
+*/
+#ifndef qh_NOmerge
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
+ void **freelistp; /* used !qh_NOmem */
+ ridgeT *ridge, **ridgep;
+ facetT *neighbor, *newfacet= NULL, *samecycle;
+ setT *vertices;
+ boolT toporient;
+ int ridgeid;
+
+ FOREACHridge_(visible->ridges) {
+ ridgeid= ridge->id;
+ neighbor= otherfacet_(ridge, visible);
+ if (neighbor->visible) {
+ if (!qh ONLYgood) {
+ if (neighbor->visitid == qh visit_id) {
+ qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */
+ qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+ }
+ }
+ }else { /* neighbor is an horizon facet */
+ toporient= (ridge->top == visible);
+ vertices= qh_setnew (qh hull_dim); /* makes sure this is quick */
+ qh_setappend (&vertices, apex);
+ qh_setappend_set (&vertices, ridge->vertices);
+ newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+ (*numnew)++;
+ if (neighbor->coplanar) {
+ newfacet->mergehorizon= True;
+ if (!neighbor->seen) {
+ newfacet->f.samecycle= newfacet;
+ neighbor->f.newcycle= newfacet;
+ }else {
+ samecycle= neighbor->f.newcycle;
+ newfacet->f.samecycle= samecycle->f.samecycle;
+ samecycle->f.samecycle= newfacet;
+ }
+ }
+ if (qh ONLYgood) {
+ if (!neighbor->simplicial)
+ qh_setappend(&(newfacet->ridges), ridge);
+ }else { /* qh_attachnewfacets */
+ if (neighbor->seen) {
+ if (neighbor->simplicial) {
+ fprintf (qh ferr, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
+ neighbor->id, visible->id);
+ qh_errexit2 (qh_ERRqhull, neighbor, visible);
+ }
+ qh_setappend (&(neighbor->neighbors), newfacet);
+ }else
+ qh_setreplace (neighbor->neighbors, visible, newfacet);
+ if (neighbor->simplicial) {
+ qh_setdel (neighbor->ridges, ridge);
+ qh_setfree (&(ridge->vertices));
+ qh_memfree (ridge, sizeof(ridgeT));
+ }else {
+ qh_setappend(&(newfacet->ridges), ridge);
+ if (toporient)
+ ridge->top= newfacet;
+ else
+ ridge->bottom= newfacet;
+ }
+ trace4((qh ferr, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
+ newfacet->id, apex->id, ridgeid, neighbor->id));
+ }
+ }
+ neighbor->seen= True;
+ } /* for each ridge */
+ if (!qh ONLYgood)
+ SETfirst_(visible->ridges)= NULL;
+ return newfacet;
+} /* makenew_nonsimplicial */
+#else /* qh_NOmerge */
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
+ return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="makenew_simplicial">-</a>
+
+ qh_makenew_simplicial( visible, apex, numnew )
+ make new facets for simplicial visible facet and apex
+
+ returns:
+ attaches new facets if (!qh.ONLYgood)
+ neighbors between newfacet and horizon
+
+ notes:
+ nop if neighbor->seen or neighbor->visible (see qh_makenew_nonsimplicial)
+
+ design:
+ locate neighboring horizon facet for visible facet
+ determine vertices and orientation
+ create new facet
+ if coplanar,
+ add new facet to f.samecycle
+ update horizon facet's neighbor list
+*/
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew) {
+ facetT *neighbor, **neighborp, *newfacet= NULL;
+ setT *vertices;
+ boolT flip, toporient;
+ int horizonskip, visibleskip;
+
+ FOREACHneighbor_(visible) {
+ if (!neighbor->seen && !neighbor->visible) {
+ vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
+ SETfirst_(vertices)= apex;
+ flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
+ if (neighbor->toporient)
+ toporient= horizonskip & 0x1;
+ else
+ toporient= (horizonskip & 0x1) ^ 0x1;
+ newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+ (*numnew)++;
+ if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
+#ifndef qh_NOmerge
+ newfacet->f.samecycle= newfacet;
+ newfacet->mergehorizon= True;
+#endif
+ }
+ if (!qh ONLYgood)
+ SETelem_(neighbor->neighbors, horizonskip)= newfacet;
+ trace4((qh ferr, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
+ newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
+ neighbor->toporient, visible->id, visibleskip, flip));
+ }
+ }
+ return newfacet;
+} /* makenew_simplicial */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="matchneighbor">-</a>
+
+ qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
+ either match subridge of newfacet with neighbor or add to hash_table
+
+ returns:
+ duplicate ridges are unmatched and marked by qh_DUPLICATEridge
+
+ notes:
+ ridge is newfacet->vertices w/o newskip vertex
+ do not allocate memory (need to free hash_table cleanly)
+ uses linear hash chains
+
+ see also:
+ qh_matchduplicates
+
+ design:
+ for each possible matching facet in qh.hash_table
+ if vertices match
+ set ismatch, if facets have opposite orientation
+ if ismatch and matching facet doesn't have a match
+ match the facets by updating their neighbor sets
+ else
+ indicate a duplicate ridge
+ set facet hyperplane for later testing
+ add facet to hashtable
+ unless the other facet was already a duplicate ridge
+ mark both facets with a duplicate ridge
+ add other facet (if defined) to hash table
+*/
+void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount) {
+ boolT newfound= False; /* True, if new facet is already in hash chain */
+ boolT same, ismatch;
+ int hash, scan;
+ facetT *facet, *matchfacet;
+ int skip, matchskip;
+
+ hash= (int)qh_gethash (hashsize, newfacet->vertices, qh hull_dim, 1,
+ SETelem_(newfacet->vertices, newskip));
+ trace4((qh ferr, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
+ newfacet->id, newskip, hash, *hashcount));
+ zinc_(Zhashlookup);
+ for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+ scan= (++scan >= hashsize ? 0 : scan)) {
+ if (facet == newfacet) {
+ newfound= True;
+ continue;
+ }
+ zinc_(Zhashtests);
+ if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+ if (SETelem_(newfacet->vertices, newskip) ==
+ SETelem_(facet->vertices, skip)) {
+ qh_precision ("two facets with the same vertices");
+ fprintf (qh ferr, "qhull precision error: Vertex sets are the same for f%d and f%d. Can not force output.\n",
+ facet->id, newfacet->id);
+ qh_errexit2 (qh_ERRprec, facet, newfacet);
+ }
+ ismatch= (same == (newfacet->toporient ^ facet->toporient));
+ matchfacet= SETelemt_(facet->neighbors, skip, facetT);
+ if (ismatch && !matchfacet) {
+ SETelem_(facet->neighbors, skip)= newfacet;
+ SETelem_(newfacet->neighbors, newskip)= facet;
+ (*hashcount)--;
+ trace4((qh ferr, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
+ facet->id, skip, newfacet->id, newskip));
+ return;
+ }
+ if (!qh PREmerge && !qh MERGEexact) {
+ qh_precision ("a ridge with more than two neighbors");
+ fprintf (qh ferr, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors. Can not continue.\n",
+ facet->id, newfacet->id, getid_(matchfacet));
+ qh_errexit2 (qh_ERRprec, facet, newfacet);
+ }
+ SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
+ newfacet->dupridge= True;
+ if (!newfacet->normal)
+ qh_setfacetplane (newfacet);
+ qh_addhash (newfacet, qh hash_table, hashsize, hash);
+ (*hashcount)++;
+ if (!facet->normal)
+ qh_setfacetplane (facet);
+ if (matchfacet != qh_DUPLICATEridge) {
+ SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
+ facet->dupridge= True;
+ if (!facet->normal)
+ qh_setfacetplane (facet);
+ if (matchfacet) {
+ matchskip= qh_setindex (matchfacet->neighbors, facet);
+ SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
+ matchfacet->dupridge= True;
+ if (!matchfacet->normal)
+ qh_setfacetplane (matchfacet);
+ qh_addhash (matchfacet, qh hash_table, hashsize, hash);
+ *hashcount += 2;
+ }
+ }
+ trace4((qh ferr, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
+ newfacet->id, newskip, facet->id, skip,
+ (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
+ ismatch, hash));
+ return; /* end of duplicate ridge */
+ }
+ }
+ if (!newfound)
+ SETelem_(qh hash_table, scan)= newfacet; /* same as qh_addhash */
+ (*hashcount)++;
+ trace4((qh ferr, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
+ newfacet->id, newskip, hash));
+} /* matchneighbor */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="matchnewfacets">-</a>
+
+ qh_matchnewfacets()
+ match newfacets in qh.newfacet_list to their newfacet neighbors
+
+ returns:
+ qh.newfacet_list with full neighbor sets
+ get vertices with nth neighbor by deleting nth vertex
+ if qh.PREmerge/MERGEexact or qh.FORCEoutput
+ sets facet->flippped if flipped normal (also prevents point partitioning)
+ if duplicate ridges and qh.PREmerge/MERGEexact
+ sets facet->dupridge
+ missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
+
+ notes:
+ newfacets already have neighbor[0] (horizon facet)
+ assumes qh.hash_table is NULL
+ vertex->neighbors has not been updated yet
+ do not allocate memory after qh.hash_table (need to free it cleanly)
+
+ design:
+ delete neighbor sets for all new facets
+ initialize a hash table
+ for all new facets
+ match facet with neighbors
+ if unmatched facets (due to duplicate ridges)
+ for each new facet with a duplicate ridge
+ match it with a facet
+ check for flipped facets
+*/
+void qh_matchnewfacets (void /* qh newfacet_list */) {
+ int numnew=0, hashcount=0, newskip;
+ facetT *newfacet, *neighbor;
+ int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
+ setT *neighbors;
+#ifndef qh_NOtrace
+ int facet_i, facet_n, numfree= 0;
+ facetT *facet;
+#endif
+
+ trace1((qh ferr, "qh_matchnewfacets: match neighbors for new facets.\n"));
+ FORALLnew_facets {
+ numnew++;
+ { /* inline qh_setzero (newfacet->neighbors, 1, qh hull_dim); */
+ neighbors= newfacet->neighbors;
+ neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
+ memset ((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
+ }
+ }
+ qh_newhashtable (numnew*(qh hull_dim-1)); /* twice what is normally needed,
+ but every ridge could be DUPLICATEridge */
+ hashsize= qh_setsize (qh hash_table);
+ FORALLnew_facets {
+ for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
+ qh_matchneighbor (newfacet, newskip, hashsize, &hashcount);
+#if 0 /* use the following to trap hashcount errors */
+ {
+ int count= 0, k;
+ facetT *facet, *neighbor;
+
+ count= 0;
+ FORALLfacet_(qh newfacet_list) { /* newfacet already in use */
+ for (k=1; k < qh hull_dim; k++) {
+ neighbor= SETelemt_(facet->neighbors, k, facetT);
+ if (!neighbor || neighbor == qh_DUPLICATEridge)
+ count++;
+ }
+ if (facet == newfacet)
+ break;
+ }
+ if (count != hashcount) {
+ fprintf (qh ferr, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
+ newfacet->id, hashcount, count);
+ qh_errexit (qh_ERRqhull, newfacet, NULL);
+ }
+ }
+#endif /* end of trap code */
+ }
+ if (hashcount) {
+ FORALLnew_facets {
+ if (newfacet->dupridge) {
+ FOREACHneighbor_i_(newfacet) {
+ if (neighbor == qh_DUPLICATEridge) {
+ qh_matchduplicates (newfacet, neighbor_i, hashsize, &hashcount);
+ /* this may report MERGEfacet */
+ }
+ }
+ }
+ }
+ }
+ if (hashcount) {
+ fprintf (qh ferr, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
+ hashcount);
+ qh_printhashtable (qh ferr);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+#ifndef qh_NOtrace
+ if (qh IStracing >= 2) {
+ FOREACHfacet_i_(qh hash_table) {
+ if (!facet)
+ numfree++;
+ }
+ fprintf (qh ferr, "qh_matchnewfacets: %d new facets, %d unused hash entries . hashsize %d\n",
+ numnew, numfree, qh_setsize (qh hash_table));
+ }
+#endif /* !qh_NOtrace */
+ qh_setfree (&qh hash_table);
+ if (qh PREmerge || qh MERGEexact) {
+ if (qh IStracing >= 4)
+ qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
+ FORALLnew_facets {
+ if (newfacet->normal)
+ qh_checkflipped (newfacet, NULL, qh_ALL);
+ }
+ }else if (qh FORCEoutput)
+ qh_checkflipped_all (qh newfacet_list); /* prints warnings for flipped */
+} /* matchnewfacets */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="matchvertices">-</a>
+
+ qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
+ tests whether vertices match with a single skip
+ starts match at firstindex since all new facets have a common vertex
+
+ returns:
+ true if matched vertices
+ skip index for each set
+ sets same iff vertices have the same orientation
+
+ notes:
+ assumes skipA is in A and both sets are the same size
+
+ design:
+ set up pointers
+ scan both sets checking for a match
+ test orientation
+*/
+boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA,
+ setT *verticesB, int *skipB, boolT *same) {
+ vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
+
+ elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
+ elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
+ skipAp= SETelemaddr_(verticesA, skipA, vertexT);
+ do if (elemAp != skipAp) {
+ while (*elemAp != *elemBp++) {
+ if (skipBp)
+ return False;
+ skipBp= elemBp; /* one extra like FOREACH */
+ }
+ }while(*(++elemAp));
+ if (!skipBp)
+ skipBp= ++elemBp;
+ *skipB= SETindex_(verticesB, skipB);
+ *same= !(((ptr_intT)skipA & 0x1) ^ ((ptr_intT)*skipB & 0x1));
+ trace4((qh ferr, "qh_matchvertices: matched by skip %d (v%d) and skip %d (v%d) same? %d\n",
+ skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
+ return (True);
+} /* matchvertices */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="newfacet">-</a>
+
+ qh_newfacet()
+ return a new facet
+
+ returns:
+ all fields initialized or cleared (NULL)
+ preallocates neighbors set
+*/
+facetT *qh_newfacet(void) {
+ facetT *facet;
+ void **freelistp; /* used !qh_NOmem */
+
+ qh_memalloc_(sizeof(facetT), freelistp, facet, facetT);
+ memset ((char *)facet, 0, sizeof(facetT));
+ if (qh facet_id == qh tracefacet_id)
+ qh tracefacet= facet;
+ facet->id= qh facet_id++;
+ facet->neighbors= qh_setnew(qh hull_dim);
+#if !qh_COMPUTEfurthest
+ facet->furthestdist= 0.0;
+#endif
+#if qh_MAXoutside
+ if (qh FORCEoutput && qh APPROXhull)
+ facet->maxoutside= qh MINoutside;
+ else
+ facet->maxoutside= qh DISTround;
+#endif
+ facet->simplicial= True;
+ facet->good= True;
+ facet->newfacet= True;
+ trace4((qh ferr, "qh_newfacet: created facet f%d\n", facet->id));
+ return (facet);
+} /* newfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="newridge">-</a>
+
+ qh_newridge()
+ return a new ridge
+*/
+ridgeT *qh_newridge(void) {
+ ridgeT *ridge;
+ void **freelistp; /* used !qh_NOmem */
+
+ qh_memalloc_(sizeof(ridgeT), freelistp, ridge, ridgeT);
+ memset ((char *)ridge, 0, sizeof(ridgeT));
+ zinc_(Ztotridges);
+ if (qh ridge_id == 0xFFFFFF) {
+ fprintf(qh ferr, "\
+qhull warning: more than %d ridges. ID field overflows and two ridges\n\
+may have the same identifier. Otherwise output ok.\n", 0xFFFFFF);
+ }
+ ridge->id= qh ridge_id++;
+ trace4((qh ferr, "qh_newridge: created ridge r%d\n", ridge->id));
+ return (ridge);
+} /* newridge */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="pointid">-</a>
+
+ qh_pointid( )
+ return id for a point,
+ returns -3 if null, -2 if interior, or -1 if not known
+
+ alternative code:
+ unsigned long id;
+ id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
+
+ notes:
+ if point not in point array
+ the code does a comparison of unrelated pointers.
+*/
+int qh_pointid (pointT *point) {
+ long offset, id;
+
+ if (!point)
+ id= -3;
+ else if (point == qh interior_point)
+ id= -2;
+ else if (point >= qh first_point
+ && point < qh first_point + qh num_points * qh hull_dim) {
+ offset= point - qh first_point;
+ id= offset / qh hull_dim;
+ }else if ((id= qh_setindex (qh other_points, point)) != -1)
+ id += qh num_points;
+ else
+ id= -1;
+ return (int) id;
+} /* pointid */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="removefacet">-</a>
+
+ qh_removefacet( facet )
+ unlinks facet from qh.facet_list,
+
+ returns:
+ updates qh.facet_list .newfacet_list .facet_next visible_list
+ decrements qh.num_facets
+
+ see:
+ qh_appendfacet
+*/
+void qh_removefacet(facetT *facet) {
+ facetT *next= facet->next, *previous= facet->previous;
+
+ if (facet == qh newfacet_list)
+ qh newfacet_list= next;
+ if (facet == qh facet_next)
+ qh facet_next= next;
+ if (facet == qh visible_list)
+ qh visible_list= next;
+ if (previous) {
+ previous->next= next;
+ next->previous= previous;
+ }else { /* 1st facet in qh facet_list */
+ qh facet_list= next;
+ qh facet_list->previous= NULL;
+ }
+ qh num_facets--;
+ trace4((qh ferr, "qh_removefacet: remove f%d from facet_list\n", facet->id));
+} /* removefacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="removevertex">-</a>
+
+ qh_removevertex( vertex )
+ unlinks vertex from qh.vertex_list,
+
+ returns:
+ updates qh.vertex_list .newvertex_list
+ decrements qh.num_vertices
+*/
+void qh_removevertex(vertexT *vertex) {
+ vertexT *next= vertex->next, *previous= vertex->previous;
+
+ if (vertex == qh newvertex_list)
+ qh newvertex_list= next;
+ if (previous) {
+ previous->next= next;
+ next->previous= previous;
+ }else { /* 1st vertex in qh vertex_list */
+ qh vertex_list= vertex->next;
+ qh vertex_list->previous= NULL;
+ }
+ qh num_vertices--;
+ trace4((qh ferr, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
+} /* removevertex */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="updatevertices">-</a>
+
+ qh_updatevertices()
+ update vertex neighbors and delete interior vertices
+
+ returns:
+ if qh.VERTEXneighbors, updates neighbors for each vertex
+ if qh.newvertex_list,
+ removes visible neighbors from vertex neighbors
+ if qh.newfacet_list
+ adds new facets to vertex neighbors
+ if qh.visible_list
+ interior vertices added to qh.del_vertices for later partitioning
+
+ design:
+ if qh.VERTEXneighbors
+ deletes references to visible facets from vertex neighbors
+ appends new facets to the neighbor list for each vertex
+ checks all vertices of visible facets
+ removes visible facets from neighbor lists
+ marks unused vertices for deletion
+*/
+void qh_updatevertices (void /*qh newvertex_list, newfacet_list, visible_list*/) {
+ facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+ vertexT *vertex, **vertexp;
+
+ trace3((qh ferr, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
+ if (qh VERTEXneighbors) {
+ FORALLvertex_(qh newvertex_list) {
+ FOREACHneighbor_(vertex) {
+ if (neighbor->visible)
+ SETref_(neighbor)= NULL;
+ }
+ qh_setcompact (vertex->neighbors);
+ }
+ FORALLnew_facets {
+ FOREACHvertex_(newfacet->vertices)
+ qh_setappend (&vertex->neighbors, newfacet);
+ }
+ FORALLvisible_facets {
+ FOREACHvertex_(visible->vertices) {
+ if (!vertex->newlist && !vertex->deleted) {
+ FOREACHneighbor_(vertex) { /* this can happen under merging */
+ if (!neighbor->visible)
+ break;
+ }
+ if (neighbor)
+ qh_setdel (vertex->neighbors, visible);
+ else {
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+ trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
+ qh_pointid(vertex->point), vertex->id, visible->id));
+ }
+ }
+ }
+ }
+ }else { /* !VERTEXneighbors */
+ FORALLvisible_facets {
+ FOREACHvertex_(visible->vertices) {
+ if (!vertex->newlist && !vertex->deleted) {
+ vertex->deleted= True;
+ qh_setappend (&qh del_vertices, vertex);
+ trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
+ qh_pointid(vertex->point), vertex->id, visible->id));
+ }
+ }
+ }
+ }
+} /* updatevertices */
+
+
+
diff --git a/extern/qhull/src/poly.h b/extern/qhull/src/poly.h
new file mode 100644
index 00000000000..294ec9527fc
--- /dev/null
+++ b/extern/qhull/src/poly.h
@@ -0,0 +1,290 @@
+/*<html><pre> -<a href="qh-poly.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ poly.h
+ header file for poly.c and poly2.c
+
+ see qh-poly.htm, qhull.h and poly.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+/*=============== constants ========================== */
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="ALGORITHMfault">-</a>
+
+ ALGORITHMfault
+ use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="DATAfault">-</a>
+
+ DATAfault
+ use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="DUPLICATEridge">-</a>
+
+ DUPLICATEridge
+ special value for facet->neighbor to indicate a duplicate ridge
+
+ notes:
+ set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_DUPLICATEridge ( facetT * ) 1L
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="MERGEridge">-</a>
+
+ MERGEridge flag in facet
+ special value for facet->neighbor to indicate a merged ridge
+
+ notes:
+ set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_MERGEridge ( facetT * ) 2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLfacet_">-</a>
+
+ FORALLfacet_( facetlist ) { ... }
+ assign 'facet' to each facet in facetlist
+
+ notes:
+ uses 'facetT *facet;'
+ assumes last facet is a sentinel
+
+ see:
+ FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLnew_facets">-</a>
+
+ FORALLnew_facets { ... }
+ assign 'newfacet' to each facet in qh.newfacet_list
+
+ notes:
+ uses 'facetT *newfacet;'
+ at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvertex_">-</a>
+
+ FORALLvertex_( vertexlist ) { ... }
+ assign 'vertex' to each vertex in vertexlist
+
+ notes:
+ uses 'vertexT *vertex;'
+ at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvisible_facets">-</a>
+
+ FORALLvisible_facets { ... }
+ assign 'visible' to each visible facet in qh.visible_list
+
+ notes:
+ uses 'vacetT *visible;'
+ at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLsame_">-</a>
+
+ FORALLsame_( newfacet ) { ... }
+ assign 'same' to each facet in newfacet->f.samecycle
+
+ notes:
+ uses 'facetT *same;'
+ stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLsame_cycle_">-</a>
+
+ FORALLsame_cycle_( newfacet ) { ... }
+ assign 'same' to each facet in newfacet->f.samecycle
+
+ notes:
+ uses 'facetT *same;'
+ at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+ for (same= newfacet->f.samecycle; \
+ same; same= (same == newfacet ? NULL : same->f.samecycle))
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighborA_">-</a>
+
+ FOREACHneighborA_( facet ) { ... }
+ assign 'neighborA' to each neighbor in facet->neighbors
+
+ FOREACHneighborA_( vertex ) { ... }
+ assign 'neighborA' to each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighborA, **neighborAp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighborA_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvisible_">-</a>
+
+ FOREACHvisible_( facets ) { ... }
+ assign 'visible' to each facet in facets
+
+ notes:
+ uses 'facetT *facet, *facetp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHnewfacet_">-</a>
+
+ FOREACHnewfacet_( facets ) { ... }
+ assign 'newfacet' to each facet in facets
+
+ notes:
+ uses 'facetT *newfacet, *newfacetp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertexA_">-</a>
+
+ FOREACHvertexA_( vertices ) { ... }
+ assign 'vertexA' to each vertex in vertices
+
+ notes:
+ uses 'vertexT *vertexA, *vertexAp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertexreverse12_">-</a>
+
+ FOREACHvertexreverse12_( vertices ) { ... }
+ assign 'vertex' to each vertex in vertices
+ reverse order of first two vertices
+
+ notes:
+ uses 'vertexT *vertex, *vertexp;'
+ see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly.c in alphabetical order ================*/
+
+void qh_appendfacet(facetT *facet);
+void qh_appendvertex(vertexT *vertex);
+void qh_attachnewfacets (void);
+boolT qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
+void qh_delfacet(facetT *facet);
+void qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
+setT *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
+void qh_makenewplanes ( void /* newfacet_list */);
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
+void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
+ int *hashcount);
+void qh_matchnewfacets (void);
+boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA,
+ setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(void);
+ridgeT *qh_newridge(void);
+int qh_pointid (pointT *point);
+void qh_removefacet(facetT *facet);
+void qh_removevertex(vertexT *vertex);
+void qh_updatevertices (void);
+
+
+/*========== -prototypes poly2.c in alphabetical order ===========*/
+
+void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
+void qh_check_bestdist (void);
+void qh_check_maxout (void);
+void qh_check_output (void);
+void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
+void qh_check_points(void);
+void qh_checkconvex(facetT *facetlist, int fault);
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
+void qh_checkflipped_all (facetT *facetlist);
+void qh_checkpolygon(facetT *facetlist);
+void qh_checkvertex (vertexT *vertex);
+void qh_clearcenters (qh_CENTER type);
+void qh_createsimplex(setT *vertices);
+void qh_delridge(ridgeT *ridge);
+void qh_delvertex (vertexT *vertex);
+setT *qh_facet3vertex (facetT *facet);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+ realT *bestdist, boolT *isoutside);
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+ int *numpart);
+int qh_findgood (facetT *facetlist, int goodhorizon);
+void qh_findgood_all (facetT *facetlist);
+void qh_furthestnext (void /* qh facet_list */);
+void qh_furthestout (facetT *facet);
+void qh_infiniteloop (facetT *facet);
+void qh_initbuild(void);
+void qh_initialhull(setT *vertices);
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex (pointT *point, setT *vertices);
+vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void qh_nearcoplanar ( void /* qh.facet_list */);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+int qh_newhashtable(int newsize);
+vertexT *qh_newvertex(pointT *point);
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
+void qh_outcoplanar (void /* facet_list */);
+pointT *qh_point (int id);
+void qh_point_add (setT *set, pointT *point, void *elem);
+setT *qh_pointfacet (void /*qh facet_list*/);
+setT *qh_pointvertex (void /*qh facet_list*/);
+void qh_prependfacet(facetT *facet, facetT **facetlist);
+void qh_printhashtable(FILE *fp);
+void qh_printlists (void);
+void qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
+void qh_setvoronoi_all (void);
+void qh_triangulate (void /*qh facet_list*/);
+void qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
+void qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void qh_triangulate_mirror (facetT *facetA, facetT *facetB);
+void qh_triangulate_null (facetT *facetA);
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
+setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
+void qh_vertexneighbors (void /*qh facet_list*/);
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+
+#endif /* qhDEFpoly */
diff --git a/extern/qhull/src/poly2.c b/extern/qhull/src/poly2.c
new file mode 100644
index 00000000000..713faab8bed
--- /dev/null
+++ b/extern/qhull/src/poly2.c
@@ -0,0 +1,3070 @@
+/*<html><pre> -<a href="qh-poly.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ poly2.c
+ implements polygons and simplices
+
+ see qh-poly.htm, poly.h and qhull.h
+
+ frequently used code is in poly.c
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="addhash">-</a>
+
+ qh_addhash( newelem, hashtable, hashsize, hash )
+ add newelem to linear hash table at hash if not already there
+*/
+void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash) {
+ int scan;
+ void *elem;
+
+ for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
+ scan= (++scan >= hashsize ? 0 : scan)) {
+ if (elem == newelem)
+ break;
+ }
+ /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
+ if (!elem)
+ SETelem_(hashtable, scan)= newelem;
+} /* addhash */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="check_bestdist">-</a>
+
+ qh_check_bestdist()
+ check that all points are within max_outside of the nearest facet
+ if qh.ONLYgood,
+ ignores !good facets
+
+ see:
+ qh_check_maxout(), qh_outerinner()
+
+ notes:
+ only called from qh_check_points()
+ seldom used since qh.MERGING is almost always set
+ if notverified>0 at end of routine
+ some points were well inside the hull. If the hull contains
+ a lens-shaped component, these points were not verified. Use
+ options 'Qi Tv' to verify all points. (Exhaustive check also verifies)
+
+ design:
+ determine facet for each point (if any)
+ for each point
+ start with the assigned facet or with the first facet
+ find the best facet for the point and check all coplanar facets
+ error if point is outside of facet
+*/
+void qh_check_bestdist (void) {
+ boolT waserror= False, unassigned;
+ facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
+ facetT *facetlist;
+ realT dist, maxoutside, maxdist= -REALmax;
+ pointT *point;
+ int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
+ setT *facets;
+
+ trace1((qh ferr, "qh_check_bestdist: check points below nearest facet. Facet_list f%d\n",
+ qh facet_list->id));
+ maxoutside= qh_maxouter();
+ maxoutside += qh DISTround;
+ /* one more qh.DISTround for check computation */
+ trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
+ facets= qh_pointfacet (/*qh facet_list*/);
+ if (!qh_QUICKhelp && qh PRINTprecision)
+ fprintf (qh ferr, "\n\
+qhull output completed. Verifying that %d points are\n\
+below %2.2g of the nearest %sfacet.\n",
+ qh_setsize(facets), maxoutside, (qh ONLYgood ? "good " : ""));
+ FOREACHfacet_i_(facets) { /* for each point with facet assignment */
+ if (facet)
+ unassigned= False;
+ else {
+ unassigned= True;
+ facet= qh facet_list;
+ }
+ point= qh_point(facet_i);
+ if (point == qh GOODpointp)
+ continue;
+ qh_distplane(point, facet, &dist);
+ numpart++;
+ bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
+ /* occurs after statistics reported */
+ maximize_(maxdist, dist);
+ if (dist > maxoutside) {
+ if (qh ONLYgood && !bestfacet->good
+ && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
+ && dist > maxoutside))
+ notgood++;
+ else {
+ waserror= True;
+ fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+ facet_i, bestfacet->id, dist, maxoutside);
+ if (errfacet1 != bestfacet) {
+ errfacet2= errfacet1;
+ errfacet1= bestfacet;
+ }
+ }
+ }else if (unassigned && dist < -qh MAXcoplanar)
+ notverified++;
+ }
+ qh_settempfree (&facets);
+ if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
+ fprintf(qh ferr, "\n%d points were well inside the hull. If the hull contains\n\
+a lens-shaped component, these points were not verified. Use\n\
+options 'Qci Tv' to verify all points.\n", notverified);
+ if (maxdist > qh outside_err) {
+ fprintf( qh ferr, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull. The maximum value (qh.outside_err) is %6.2g\n",
+ maxdist, qh outside_err);
+ qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+ }else if (waserror && qh outside_err > REALmax/2)
+ qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+ else if (waserror)
+ ; /* the error was logged to qh.ferr but does not effect the output */
+ trace0((qh ferr, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
+} /* check_bestdist */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="check_maxout">-</a>
+
+ qh_check_maxout()
+ updates qh.max_outside by checking all points against bestfacet
+ if qh.ONLYgood, ignores !good facets
+
+ returns:
+ updates facet->maxoutside via qh_findbesthorizon()
+ sets qh.maxoutdone
+ if printing qh.min_vertex (qh_outerinner),
+ it is updated to the current vertices
+ removes inside/coplanar points from coplanarset as needed
+
+ notes:
+ defines coplanar as min_vertex instead of MAXcoplanar
+ may not need to check near-inside points because of qh.MAXcoplanar
+ and qh.KEEPnearinside (before it was -DISTround)
+
+ see also:
+ qh_check_bestdist()
+
+ design:
+ if qh.min_vertex is needed
+ for all neighbors of all vertices
+ test distance from vertex to neighbor
+ determine facet for each point (if any)
+ for each point with an assigned facet
+ find the best facet for the point and check all coplanar facets
+ (updates outer planes)
+ remove near-inside points from coplanar sets
+*/
+#ifndef qh_NOmerge
+void qh_check_maxout (void) {
+ facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
+ realT dist, maxoutside, minvertex, old_maxoutside;
+ pointT *point;
+ int numpart= 0, facet_i, facet_n, notgood= 0;
+ setT *facets, *vertices;
+ vertexT *vertex;
+
+ trace1((qh ferr, "qh_check_maxout: check and update maxoutside for each facet.\n"));
+ maxoutside= minvertex= 0;
+ if (qh VERTEXneighbors
+ && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
+ || qh TRACElevel || qh PRINTstatistics
+ || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
+ trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
+ vertices= qh_pointvertex (/*qh facet_list*/);
+ FORALLvertices {
+ FOREACHneighbor_(vertex) {
+ zinc_(Zdistvertex); /* distance also computed by main loop below */
+ qh_distplane (vertex->point, neighbor, &dist);
+ minimize_(minvertex, dist);
+ if (-dist > qh TRACEdist || dist > qh TRACEdist
+ || neighbor == qh tracefacet || vertex == qh tracevertex)
+ fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g from f%d\n",
+ qh_pointid (vertex->point), vertex->id, dist, neighbor->id);
+ }
+ }
+ if (qh MERGING) {
+ wmin_(Wminvertex, qh min_vertex);
+ }
+ qh min_vertex= minvertex;
+ qh_settempfree (&vertices);
+ }
+ facets= qh_pointfacet (/*qh facet_list*/);
+ do {
+ old_maxoutside= fmax_(qh max_outside, maxoutside);
+ FOREACHfacet_i_(facets) { /* for each point with facet assignment */
+ if (facet) {
+ point= qh_point(facet_i);
+ if (point == qh GOODpointp)
+ continue;
+ zinc_(Ztotcheck);
+ qh_distplane(point, facet, &dist);
+ numpart++;
+ bestfacet= qh_findbesthorizon (qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
+ if (bestfacet && dist > maxoutside) {
+ if (qh ONLYgood && !bestfacet->good
+ && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
+ && dist > maxoutside))
+ notgood++;
+ else
+ maxoutside= dist;
+ }
+ if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
+ fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n",
+ qh_pointid (point), dist, bestfacet->id);
+ }
+ }
+ }while
+ (maxoutside > 2*old_maxoutside);
+ /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
+ e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
+ zzadd_(Zcheckpart, numpart);
+ qh_settempfree (&facets);
+ wval_(Wmaxout)= maxoutside - qh max_outside;
+ wmax_(Wmaxoutside, qh max_outside);
+ qh max_outside= maxoutside;
+ qh_nearcoplanar (/*qh.facet_list*/);
+ qh maxoutdone= True;
+ trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
+ maxoutside, qh min_vertex, notgood));
+} /* check_maxout */
+#else /* qh_NOmerge */
+void qh_check_maxout (void) {
+}
+#endif
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="check_output">-</a>
+
+ qh_check_output()
+ performs the checks at the end of qhull algorithm
+ Maybe called after voronoi output. Will recompute otherwise centrums are Voronoi centers instead
+*/
+void qh_check_output (void) {
+ int i;
+
+ if (qh STOPcone)
+ return;
+ if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
+ qh_checkpolygon (qh facet_list);
+ qh_checkflipped_all (qh facet_list);
+ qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+ }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) {
+ qh_checkflipped_all (qh facet_list);
+ qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+ }
+} /* check_output */
+
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="check_point">-</a>
+
+ qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
+ check that point is less than maxoutside from facet
+*/
+void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
+ realT dist;
+
+ /* occurs after statistics reported */
+ qh_distplane(point, facet, &dist);
+ if (dist > *maxoutside) {
+ if (*errfacet1 != facet) {
+ *errfacet2= *errfacet1;
+ *errfacet1= facet;
+ }
+ fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+ qh_pointid(point), facet->id, dist, *maxoutside);
+ }
+ maximize_(*maxdist, dist);
+} /* qh_check_point */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="check_points">-</a>
+
+ qh_check_points()
+ checks that all points are inside all facets
+
+ notes:
+ if many points and qh_check_maxout not called (i.e., !qh.MERGING),
+ calls qh_findbesthorizon (seldom done).
+ ignores flipped facets
+ maxoutside includes 2 qh.DISTrounds
+ one qh.DISTround for the computed distances in qh_check_points
+ qh_printafacet and qh_printsummary needs only one qh.DISTround
+ the computation for qh.VERIFYdirect does not account for qh.other_points
+
+ design:
+ if many points
+ use qh_check_bestdist()
+ else
+ for all facets
+ for all points
+ check that point is inside facet
+*/
+void qh_check_points (void) {
+ facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
+ realT total, maxoutside, maxdist= -REALmax;
+ pointT *point, **pointp, *pointtemp;
+ boolT testouter;
+
+ maxoutside= qh_maxouter();
+ maxoutside += qh DISTround;
+ /* one more qh.DISTround for check computation */
+ trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n",
+ maxoutside));
+ if (qh num_good) /* miss counts other_points and !good facets */
+ total= (float) qh num_good * qh num_points;
+ else
+ total= (float) qh num_facets * qh num_points;
+ if (total >= qh_VERIFYdirect && !qh maxoutdone) {
+ if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
+ fprintf (qh ferr, "\n\
+qhull input warning: merging without checking outer planes ('Q5' or 'Po').\n\
+Verify may report that a point is outside of a facet.\n");
+ qh_check_bestdist();
+ }else {
+ if (qh_MAXoutside && qh maxoutdone)
+ testouter= True;
+ else
+ testouter= False;
+ if (!qh_QUICKhelp) {
+ if (qh MERGEexact)
+ fprintf (qh ferr, "\n\
+qhull input warning: exact merge ('Qx'). Verify may report that a point\n\
+is outside of a facet. See qh-optq.htm#Qx\n");
+ else if (qh SKIPcheckmax || qh NOnearinside)
+ fprintf (qh ferr, "\n\
+qhull input warning: no outer plane check ('Q5') or no processing of\n\
+near-inside points ('Q8'). Verify may report that a point is outside\n\
+of a facet.\n");
+ }
+ if (qh PRINTprecision) {
+ if (testouter)
+ fprintf (qh ferr, "\n\
+Output completed. Verifying that all points are below outer planes of\n\
+all %sfacets. Will make %2.0f distance computations.\n",
+ (qh ONLYgood ? "good " : ""), total);
+ else
+ fprintf (qh ferr, "\n\
+Output completed. Verifying that all points are below %2.2g of\n\
+all %sfacets. Will make %2.0f distance computations.\n",
+ maxoutside, (qh ONLYgood ? "good " : ""), total);
+ }
+ FORALLfacets {
+ if (!facet->good && qh ONLYgood)
+ continue;
+ if (facet->flipped)
+ continue;
+ if (!facet->normal) {
+ fprintf( qh ferr, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
+ continue;
+ }
+ if (testouter) {
+#if qh_MAXoutside
+ maxoutside= facet->maxoutside + 2* qh DISTround;
+ /* one DISTround to actual point and another to computed point */
+#endif
+ }
+ FORALLpoints {
+ if (point != qh GOODpointp)
+ qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+ }
+ FOREACHpoint_(qh other_points) {
+ if (point != qh GOODpointp)
+ qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+ }
+ }
+ if (maxdist > qh outside_err) {
+ fprintf( qh ferr, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull. The maximum value (qh.outside_err) is %6.2g\n",
+ maxdist, qh outside_err );
+ qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+ }else if (errfacet1 && qh outside_err > REALmax/2)
+ qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+ else if (errfacet1)
+ ; /* the error was logged to qh.ferr but does not effect the output */
+ trace0((qh ferr, "qh_check_points: max distance outside %2.2g\n", maxdist));
+ }
+} /* check_points */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkconvex">-</a>
+
+ qh_checkconvex( facetlist, fault )
+ check that each ridge in facetlist is convex
+ fault = qh_DATAfault if reporting errors
+ = qh_ALGORITHMfault otherwise
+
+ returns:
+ counts Zconcaveridges and Zcoplanarridges
+ errors if concaveridge or if merging an coplanar ridge
+
+ note:
+ if not merging,
+ tests vertices for neighboring simplicial facets
+ else if ZEROcentrum,
+ tests vertices for neighboring simplicial facets
+ else
+ tests centrums of neighboring facets
+
+ design:
+ for all facets
+ report flipped facets
+ if ZEROcentrum and simplicial neighbors
+ test vertices for neighboring simplicial facets
+ else
+ test centrum against all neighbors
+*/
+void qh_checkconvex(facetT *facetlist, int fault) {
+ facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
+ vertexT *vertex;
+ realT dist;
+ pointT *centrum;
+ boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
+ int neighbor_i;
+
+ trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n"));
+ if (!qh RERUN) {
+ zzval_(Zconcaveridges)= 0;
+ zzval_(Zcoplanarridges)= 0;
+ }
+ FORALLfacet_(facetlist) {
+ if (facet->flipped) {
+ qh_precision ("flipped facet");
+ fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n",
+ facet->id);
+ errfacet1= facet;
+ waserror= True;
+ continue;
+ }
+ if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
+ allsimplicial= False;
+ else {
+ allsimplicial= True;
+ neighbor_i= 0;
+ FOREACHneighbor_(facet) {
+ vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+ if (!neighbor->simplicial || neighbor->tricoplanar) {
+ allsimplicial= False;
+ continue;
+ }
+ qh_distplane (vertex->point, neighbor, &dist);
+ if (dist > -qh DISTround) {
+ if (fault == qh_DATAfault) {
+ qh_precision ("coplanar or concave ridge");
+ fprintf (qh ferr, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
+ qh_errexit(qh_ERRsingular, NULL, NULL);
+ }
+ if (dist > qh DISTround) {
+ zzinc_(Zconcaveridges);
+ qh_precision ("concave ridge");
+ fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n",
+ facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+ errfacet1= facet;
+ errfacet2= neighbor;
+ waserror= True;
+ }else if (qh ZEROcentrum) {
+ if (dist > 0) { /* qh_checkzero checks that dist < - qh DISTround */
+ zzinc_(Zcoplanarridges);
+ qh_precision ("coplanar ridge");
+ fprintf (qh ferr, "qhull precision error: f%d is clearly not convex to f%d, since p%d (v%d) is %6.4g above\n",
+ facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+ errfacet1= facet;
+ errfacet2= neighbor;
+ waserror= True;
+ }
+ }else {
+ zzinc_(Zcoplanarridges);
+ qh_precision ("coplanar ridge");
+ trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g during p%d\n",
+ facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
+ }
+ }
+ }
+ }
+ if (!allsimplicial) {
+ if (qh CENTERtype == qh_AScentrum) {
+ if (!facet->center)
+ facet->center= qh_getcentrum (facet);
+ centrum= facet->center;
+ }else {
+ if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
+ centrum_warning= True;
+ fprintf (qh ferr, "qhull note: recomputing centrums for convexity test. This may lead to false, precision errors.\n");
+ }
+ centrum= qh_getcentrum(facet);
+ tempcentrum= True;
+ }
+ FOREACHneighbor_(facet) {
+ if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
+ continue;
+ if (facet->tricoplanar || neighbor->tricoplanar)
+ continue;
+ zzinc_(Zdistconvex);
+ qh_distplane (centrum, neighbor, &dist);
+ if (dist > qh DISTround) {
+ zzinc_(Zconcaveridges);
+ qh_precision ("concave ridge");
+ fprintf (qh ferr, "qhull precision error: f%d is concave to f%d. Centrum of f%d is %6.4g above f%d\n",
+ facet->id, neighbor->id, facet->id, dist, neighbor->id);
+ errfacet1= facet;
+ errfacet2= neighbor;
+ waserror= True;
+ }else if (dist >= 0.0) { /* if arithmetic always rounds the same,
+ can test against centrum radius instead */
+ zzinc_(Zcoplanarridges);
+ qh_precision ("coplanar ridge");
+ fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d. Centrum of f%d is %6.4g above f%d\n",
+ facet->id, neighbor->id, facet->id, dist, neighbor->id);
+ errfacet1= facet;
+ errfacet2= neighbor;
+ waserror= True;
+ }
+ }
+ if (tempcentrum)
+ qh_memfree(centrum, qh normal_size);
+ }
+ }
+ if (waserror && !qh FORCEoutput)
+ qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+} /* checkconvex */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkfacet">-</a>
+
+ qh_checkfacet( facet, newmerge, waserror )
+ checks for consistency errors in facet
+ newmerge set if from merge.c
+
+ returns:
+ sets waserror if any error occurs
+
+ checks:
+ vertex ids are inverse sorted
+ unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
+ if non-simplicial, at least as many ridges as neighbors
+ neighbors are not duplicated
+ ridges are not duplicated
+ in 3-d, ridges=verticies
+ (qh.hull_dim-1) ridge vertices
+ neighbors are reciprocated
+ ridge neighbors are facet neighbors and a ridge for every neighbor
+ simplicial neighbors match facetintersect
+ vertex intersection matches vertices of common ridges
+ vertex neighbors and facet vertices agree
+ all ridges have distinct vertex sets
+
+ notes:
+ uses neighbor->seen
+
+ design:
+ check sets
+ check vertices
+ check sizes of neighbors and vertices
+ check for qh_MERGEridge and qh_DUPLICATEridge flags
+ check neighbor set
+ check ridge set
+ check ridges, neighbors, and vertices
+*/
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
+ facetT *neighbor, **neighborp, *errother=NULL;
+ ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
+ vertexT *vertex, **vertexp;
+ unsigned previousid= INT_MAX;
+ int numneighbors, numvertices, numridges=0, numRvertices=0;
+ boolT waserror= False;
+ int skipA, skipB, ridge_i, ridge_n, i;
+ setT *intersection;
+
+ if (facet->visible) {
+ fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
+ facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ if (!facet->normal) {
+ fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a normal\n",
+ facet->id);
+ waserror= True;
+ }
+ qh_setcheck (facet->vertices, "vertices for f", facet->id);
+ qh_setcheck (facet->ridges, "ridges for f", facet->id);
+ qh_setcheck (facet->outsideset, "outsideset for f", facet->id);
+ qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id);
+ qh_setcheck (facet->neighbors, "neighbors for f", facet->id);
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->deleted) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
+ qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+ waserror= True;
+ }
+ if (vertex->id >= previousid) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
+ waserror= True;
+ break;
+ }
+ previousid= vertex->id;
+ }
+ numneighbors= qh_setsize(facet->neighbors);
+ numvertices= qh_setsize(facet->vertices);
+ numridges= qh_setsize(facet->ridges);
+ if (facet->simplicial) {
+ if (numvertices+numneighbors != 2*qh hull_dim
+ && !facet->degenerate && !facet->redundant) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
+ facet->id, numvertices, numneighbors);
+ qh_setprint (qh ferr, "", facet->neighbors);
+ waserror= True;
+ }
+ }else { /* non-simplicial */
+ if (!newmerge
+ &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
+ && !facet->degenerate && !facet->redundant) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
+ facet->id, numvertices, numneighbors);
+ waserror= True;
+ }
+ /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
+ if (numridges < numneighbors
+ ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
+ ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
+ if (!facet->degenerate && !facet->redundant) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) > #vertices %d or (2-d) not all 2\n",
+ facet->id, numridges, numneighbors, numvertices);
+ waserror= True;
+ }
+ }
+ }
+ FOREACHneighbor_(facet) {
+ if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ neighbor->seen= True;
+ }
+ FOREACHneighbor_(facet) {
+ if (!qh_setin(neighbor->neighbors, facet)) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
+ facet->id, neighbor->id, neighbor->id, facet->id);
+ errother= neighbor;
+ waserror= True;
+ }
+ if (!neighbor->seen) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
+ facet->id, neighbor->id);
+ errother= neighbor;
+ waserror= True;
+ }
+ neighbor->seen= False;
+ }
+ FOREACHridge_(facet->ridges) {
+ qh_setcheck (ridge->vertices, "vertices for r", ridge->id);
+ ridge->seen= False;
+ }
+ FOREACHridge_(facet->ridges) {
+ if (ridge->seen) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
+ facet->id, ridge->id);
+ errridge= ridge;
+ waserror= True;
+ }
+ ridge->seen= True;
+ numRvertices= qh_setsize(ridge->vertices);
+ if (numRvertices != qh hull_dim - 1) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
+ ridge->top->id, ridge->bottom->id, numRvertices);
+ errridge= ridge;
+ waserror= True;
+ }
+ neighbor= otherfacet_(ridge, facet);
+ neighbor->seen= True;
+ if (!qh_setin(facet->neighbors, neighbor)) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
+ facet->id, neighbor->id, ridge->id);
+ errridge= ridge;
+ waserror= True;
+ }
+ }
+ if (!facet->simplicial) {
+ FOREACHneighbor_(facet) {
+ if (!neighbor->seen) {
+ fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
+ facet->id, neighbor->id);
+ errother= neighbor;
+ waserror= True;
+ }
+ intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
+ qh_settemppush (intersection);
+ FOREACHvertex_(facet->vertices) {
+ vertex->seen= False;
+ vertex->seen2= False;
+ }
+ FOREACHvertex_(intersection)
+ vertex->seen= True;
+ FOREACHridge_(facet->ridges) {
+ if (neighbor != otherfacet_(ridge, facet))
+ continue;
+ FOREACHvertex_(ridge->vertices) {
+ if (!vertex->seen) {
+ fprintf (qh ferr, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
+ vertex->id, ridge->id, facet->id, neighbor->id);
+ qh_errexit (qh_ERRqhull, facet, ridge);
+ }
+ vertex->seen2= True;
+ }
+ }
+ if (!newmerge) {
+ FOREACHvertex_(intersection) {
+ if (!vertex->seen2) {
+ if (qh IStracing >=3 || !qh MERGING) {
+ fprintf (qh ferr, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
+ not in a ridge. This is ok under merging. Last point was p%d\n",
+ vertex->id, facet->id, neighbor->id, qh furthest_id);
+ if (!qh FORCEoutput && !qh MERGING) {
+ qh_errprint ("ERRONEOUS", facet, neighbor, NULL, vertex);
+ if (!qh MERGING)
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ }
+ }
+ }
+ }
+ qh_settempfree (&intersection);
+ }
+ }else { /* simplicial */
+ FOREACHneighbor_(facet) {
+ if (neighbor->simplicial) {
+ skipA= SETindex_(facet->neighbors, neighbor);
+ skipB= qh_setindex (neighbor->neighbors, facet);
+ if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) {
+ fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
+ facet->id, skipA, neighbor->id, skipB);
+ errother= neighbor;
+ waserror= True;
+ }
+ }
+ }
+ }
+ if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
+ FOREACHridge_i_(facet->ridges) { /* expensive */
+ for (i= ridge_i+1; i < ridge_n; i++) {
+ ridge2= SETelemt_(facet->ridges, i, ridgeT);
+ if (qh_setequal (ridge->vertices, ridge2->vertices)) {
+ fprintf (qh ferr, "qh_checkfacet: ridges r%d and r%d have the same vertices\n",
+ ridge->id, ridge2->id);
+ errridge= ridge;
+ waserror= True;
+ }
+ }
+ }
+ }
+ if (waserror) {
+ qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
+ *waserrorp= True;
+ }
+} /* checkfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkflipped_all">-</a>
+
+ qh_checkflipped_all( facetlist )
+ checks orientation of facets in list against interior point
+*/
+void qh_checkflipped_all (facetT *facetlist) {
+ facetT *facet;
+ boolT waserror= False;
+ realT dist;
+
+ if (facetlist == qh facet_list)
+ zzval_(Zflippedfacets)= 0;
+ FORALLfacet_(facetlist) {
+ if (facet->normal && !qh_checkflipped (facet, &dist, !qh_ALL)) {
+ fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
+ facet->id, dist);
+ if (!qh FORCEoutput) {
+ qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
+ waserror= True;
+ }
+ }
+ }
+ if (waserror) {
+ fprintf (qh ferr, "\n\
+A flipped facet occurs when its distance to the interior point is\n\
+greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
+ qh_errexit(qh_ERRprec, NULL, NULL);
+ }
+} /* checkflipped_all */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkpolygon">-</a>
+
+ qh_checkpolygon( facetlist )
+ checks the correctness of the structure
+
+ notes:
+ call with either qh.facet_list or qh.newfacet_list
+ checks num_facets and num_vertices if qh.facet_list
+
+ design:
+ for each facet
+ checks facet and outside set
+ initializes vertexlist
+ for each facet
+ checks vertex set
+ if checking all facets (qh.facetlist)
+ check facet count
+ if qh.VERTEXneighbors
+ check vertex neighbors and count
+ check vertex count
+*/
+void qh_checkpolygon(facetT *facetlist) {
+ facetT *facet;
+ vertexT *vertex, **vertexp, *vertexlist;
+ int numfacets= 0, numvertices= 0, numridges= 0;
+ int totvneighbors= 0, totvertices= 0;
+ boolT waserror= False, nextseen= False, visibleseen= False;
+
+ trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
+ if (facetlist != qh facet_list || qh ONLYgood)
+ nextseen= True;
+ FORALLfacet_(facetlist) {
+ if (facet == qh visible_list)
+ visibleseen= True;
+ if (!facet->visible) {
+ if (!nextseen) {
+ if (facet == qh facet_next)
+ nextseen= True;
+ else if (qh_setsize (facet->outsideset)) {
+ if (!qh NARROWhull
+#if !qh_COMPUTEfurthest
+ || facet->furthestdist >= qh MINoutside
+#endif
+ ) {
+ fprintf (qh ferr, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
+ facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ }
+ }
+ numfacets++;
+ qh_checkfacet(facet, False, &waserror);
+ }
+ }
+ if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
+ fprintf (qh ferr, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
+ qh_printlists();
+ qh_errexit (qh_ERRqhull, qh visible_list, NULL);
+ }
+ if (facetlist == qh facet_list)
+ vertexlist= qh vertex_list;
+ else if (facetlist == qh newfacet_list)
+ vertexlist= qh newvertex_list;
+ else
+ vertexlist= NULL;
+ FORALLvertex_(vertexlist) {
+ vertex->seen= False;
+ vertex->visitid= 0;
+ }
+ FORALLfacet_(facetlist) {
+ if (facet->visible)
+ continue;
+ if (facet->simplicial)
+ numridges += qh hull_dim;
+ else
+ numridges += qh_setsize (facet->ridges);
+ FOREACHvertex_(facet->vertices) {
+ vertex->visitid++;
+ if (!vertex->seen) {
+ vertex->seen= True;
+ numvertices++;
+ if (qh_pointid (vertex->point) == -1) {
+ fprintf (qh ferr, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
+ vertex->point, vertex->id, qh first_point);
+ waserror= True;
+ }
+ }
+ }
+ }
+ qh vertex_visit += numfacets;
+ if (facetlist == qh facet_list) {
+ if (numfacets != qh num_facets - qh num_visible) {
+ fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
+ numfacets, qh num_facets, qh num_visible);
+ waserror= True;
+ }
+ qh vertex_visit++;
+ if (qh VERTEXneighbors) {
+ FORALLvertices {
+ qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id);
+ if (vertex->deleted)
+ continue;
+ totvneighbors += qh_setsize (vertex->neighbors);
+ }
+ FORALLfacet_(facetlist)
+ totvertices += qh_setsize (facet->vertices);
+ if (totvneighbors != totvertices) {
+ fprintf(qh ferr, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent. Totvneighbors %d, totvertices %d\n",
+ totvneighbors, totvertices);
+ waserror= True;
+ }
+ }
+ if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
+ fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
+ numvertices, qh num_vertices - qh_setsize(qh del_vertices));
+ waserror= True;
+ }
+ if (qh hull_dim == 2 && numvertices != numfacets) {
+ fprintf (qh ferr, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
+ numvertices, numfacets);
+ waserror= True;
+ }
+ if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
+ fprintf (qh ferr, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
+ A vertex appears twice in a edge list. May occur during merging.",
+ numvertices, numfacets, numridges/2);
+ /* occurs if lots of merging and a vertex ends up twice in an edge list. e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
+ }
+ }
+ if (waserror)
+ qh_errexit(qh_ERRqhull, NULL, NULL);
+} /* checkpolygon */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="checkvertex">-</a>
+
+ qh_checkvertex( vertex )
+ check vertex for consistency
+ checks vertex->neighbors
+
+ notes:
+ neighbors checked efficiently in checkpolygon
+*/
+void qh_checkvertex (vertexT *vertex) {
+ boolT waserror= False;
+ facetT *neighbor, **neighborp, *errfacet=NULL;
+
+ if (qh_pointid (vertex->point) == -1) {
+ fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
+ waserror= True;
+ }
+ if (vertex->id >= qh vertex_id) {
+ fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
+ waserror= True;
+ }
+ if (!waserror && !vertex->deleted) {
+ if (qh_setsize (vertex->neighbors)) {
+ FOREACHneighbor_(vertex) {
+ if (!qh_setin (neighbor->vertices, vertex)) {
+ fprintf (qh ferr, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
+ errfacet= neighbor;
+ waserror= True;
+ }
+ }
+ }
+ }
+ if (waserror) {
+ qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+ qh_errexit (qh_ERRqhull, errfacet, NULL);
+ }
+} /* checkvertex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="clearcenters">-</a>
+
+ qh_clearcenters( type )
+ clear old data from facet->center
+
+ notes:
+ sets new centertype
+ nop if CENTERtype is the same
+*/
+void qh_clearcenters (qh_CENTER type) {
+ facetT *facet;
+
+ if (qh CENTERtype != type) {
+ FORALLfacets {
+ if (qh CENTERtype == qh_ASvoronoi){
+ if (facet->center) {
+ qh_memfree (facet->center, qh center_size);
+ facet->center= NULL;
+ }
+ }else /* qh CENTERtype == qh_AScentrum */ {
+ if (facet->center) {
+ qh_memfree (facet->center, qh normal_size);
+ facet->center= NULL;
+ }
+ }
+ }
+ qh CENTERtype= type;
+ }
+ trace2((qh ferr, "qh_clearcenters: switched to center type %d\n", type));
+} /* clearcenters */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="createsimplex">-</a>
+
+ qh_createsimplex( vertices )
+ creates a simplex from a set of vertices
+
+ returns:
+ initializes qh.facet_list to the simplex
+ initializes qh.newfacet_list, .facet_tail
+ initializes qh.vertex_list, .newvertex_list, .vertex_tail
+
+ design:
+ initializes lists
+ for each vertex
+ create a new facet
+ for each new facet
+ create its neighbor set
+*/
+void qh_createsimplex(setT *vertices) {
+ facetT *facet= NULL, *newfacet;
+ boolT toporient= True;
+ int vertex_i, vertex_n, nth;
+ setT *newfacets= qh_settemp (qh hull_dim+1);
+ vertexT *vertex;
+
+ qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
+ qh num_facets= qh num_vertices= qh num_visible= 0;
+ qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
+ FOREACHvertex_i_(vertices) {
+ newfacet= qh_newfacet();
+ newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n,
+ vertex_i, 0);
+ newfacet->toporient= toporient;
+ qh_appendfacet(newfacet);
+ newfacet->newfacet= True;
+ qh_appendvertex (vertex);
+ qh_setappend (&newfacets, newfacet);
+ toporient ^= True;
+ }
+ FORALLnew_facets {
+ nth= 0;
+ FORALLfacet_(qh newfacet_list) {
+ if (facet != newfacet)
+ SETelem_(newfacet->neighbors, nth++)= facet;
+ }
+ qh_settruncate (newfacet->neighbors, qh hull_dim);
+ }
+ qh_settempfree (&newfacets);
+ trace1((qh ferr, "qh_createsimplex: created simplex\n"));
+} /* createsimplex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="delridge">-</a>
+
+ qh_delridge( ridge )
+ deletes ridge from data structures it belongs to
+ frees up its memory
+
+ notes:
+ in merge.c, caller sets vertex->delridge for each vertex
+ ridges also freed in qh_freeqhull
+*/
+void qh_delridge(ridgeT *ridge) {
+ void **freelistp; /* used !qh_NOmem */
+
+ qh_setdel(ridge->top->ridges, ridge);
+ qh_setdel(ridge->bottom->ridges, ridge);
+ qh_setfree(&(ridge->vertices));
+ qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+} /* delridge */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="delvertex">-</a>
+
+ qh_delvertex( vertex )
+ deletes a vertex and frees its memory
+
+ notes:
+ assumes vertex->adjacencies have been updated if needed
+ unlinks from vertex_list
+*/
+void qh_delvertex (vertexT *vertex) {
+
+ if (vertex == qh tracevertex)
+ qh tracevertex= NULL;
+ qh_removevertex (vertex);
+ qh_setfree (&vertex->neighbors);
+ qh_memfree(vertex, sizeof(vertexT));
+} /* delvertex */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="facet3vertex">-</a>
+
+ qh_facet3vertex( )
+ return temporary set of 3-d vertices in qh_ORIENTclock order
+
+ design:
+ if simplicial facet
+ build set from facet->vertices with facet->toporient
+ else
+ for each ridge in order
+ build set from ridge's vertices
+*/
+setT *qh_facet3vertex (facetT *facet) {
+ ridgeT *ridge, *firstridge;
+ vertexT *vertex;
+ int cntvertices, cntprojected=0;
+ setT *vertices;
+
+ cntvertices= qh_setsize(facet->vertices);
+ vertices= qh_settemp (cntvertices);
+ if (facet->simplicial) {
+ if (cntvertices != 3) {
+ fprintf (qh ferr, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
+ cntvertices, facet->id);
+ qh_errexit(qh_ERRqhull, facet, NULL);
+ }
+ qh_setappend (&vertices, SETfirst_(facet->vertices));
+ if (facet->toporient ^ qh_ORIENTclock)
+ qh_setappend (&vertices, SETsecond_(facet->vertices));
+ else
+ qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices));
+ qh_setappend (&vertices, SETelem_(facet->vertices, 2));
+ }else {
+ ridge= firstridge= SETfirstt_(facet->ridges, ridgeT); /* no infinite */
+ while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) {
+ qh_setappend (&vertices, vertex);
+ if (++cntprojected > cntvertices || ridge == firstridge)
+ break;
+ }
+ if (!ridge || cntprojected != cntvertices) {
+ fprintf (qh ferr, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up. got at least %d\n",
+ facet->id, cntprojected);
+ qh_errexit(qh_ERRqhull, facet, ridge);
+ }
+ }
+ return vertices;
+} /* facet3vertex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="findbestfacet">-</a>
+
+ qh_findbestfacet( point, bestoutside, bestdist, isoutside )
+ find facet that is furthest below a point
+
+ for Delaunay triangulations,
+ Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+ Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+ returns:
+ if bestoutside is set (e.g., qh_ALL)
+ returns best facet that is not upperdelaunay
+ if Delaunay and inside, point is outside circumsphere of bestfacet
+ else
+ returns first facet below point
+ if point is inside, returns nearest, !upperdelaunay facet
+ distance to facet
+ isoutside set if outside of facet
+
+ notes:
+ this works for all distributions
+ if inside, qh_findbestfacet performs an exhaustive search
+ this may be too conservative. Sometimes it is clearly required.
+ qh_findbestfacet is not used by qhull.
+ uses qh.visit_id and qh.coplanarset
+
+ see:
+ <a href="geom.c#findbest">qh_findbest</a>
+*/
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+ realT *bestdist, boolT *isoutside) {
+ facetT *bestfacet= NULL;
+ int numpart, totpart= 0;
+
+ bestfacet= qh_findbest (point, qh facet_list,
+ bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
+ bestdist, isoutside, &totpart);
+ if (*bestdist < -qh DISTround) {
+ bestfacet= qh_findfacet_all (point, bestdist, isoutside, &numpart);
+ totpart += numpart;
+ if ((isoutside && bestoutside)
+ || (!isoutside && bestfacet->upperdelaunay)) {
+ bestfacet= qh_findbest (point, bestfacet,
+ bestoutside, False, bestoutside,
+ bestdist, isoutside, &totpart);
+ totpart += numpart;
+ }
+ }
+ trace3((qh ferr, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
+ bestfacet->id, *bestdist, *isoutside, totpart));
+ return bestfacet;
+} /* findbestfacet */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="findfacet_all">-</a>
+
+ qh_findfacet_all( point, bestdist, isoutside, numpart )
+ exhaustive search for facet below a point
+
+ for Delaunay triangulations,
+ Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+ Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+ returns:
+ returns first facet below point
+ if point is inside,
+ returns nearest facet
+ distance to facet
+ isoutside if point is outside of the hull
+ number of distance tests
+*/
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+ int *numpart) {
+ facetT *bestfacet= NULL, *facet;
+ realT dist;
+ int totpart= 0;
+
+ *bestdist= REALmin;
+ *isoutside= False;
+ FORALLfacets {
+ if (facet->flipped || !facet->normal)
+ continue;
+ totpart++;
+ qh_distplane (point, facet, &dist);
+ if (dist > *bestdist) {
+ *bestdist= dist;
+ bestfacet= facet;
+ if (dist > qh MINoutside) {
+ *isoutside= True;
+ break;
+ }
+ }
+ }
+ *numpart= totpart;
+ trace3((qh ferr, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
+ getid_(bestfacet), *bestdist, *isoutside, totpart));
+ return bestfacet;
+} /* findfacet_all */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="findgood">-</a>
+
+ qh_findgood( facetlist, goodhorizon )
+ identify good facets for qh.PRINTgood
+ if qh.GOODvertex>0
+ facet includes point as vertex
+ if !match, returns goodhorizon
+ inactive if qh.MERGING
+ if qh.GOODpoint
+ facet is visible or coplanar (>0) or not visible (<0)
+ if qh.GOODthreshold
+ facet->normal matches threshold
+ if !goodhorizon and !match,
+ selects facet with closest angle
+ sets GOODclosest
+
+ returns:
+ number of new, good facets found
+ determines facet->good
+ may update qh.GOODclosest
+
+ notes:
+ qh_findgood_all further reduces the good region
+
+ design:
+ count good facets
+ mark good facets for qh.GOODpoint
+ mark good facets for qh.GOODthreshold
+ if necessary
+ update qh.GOODclosest
+*/
+int qh_findgood (facetT *facetlist, int goodhorizon) {
+ facetT *facet, *bestfacet= NULL;
+ realT angle, bestangle= REALmax, dist;
+ int numgood=0;
+
+ FORALLfacet_(facetlist) {
+ if (facet->good)
+ numgood++;
+ }
+ if (qh GOODvertex>0 && !qh MERGING) {
+ FORALLfacet_(facetlist) {
+ if (!qh_isvertex (qh GOODvertexp, facet->vertices)) {
+ facet->good= False;
+ numgood--;
+ }
+ }
+ }
+ if (qh GOODpoint && numgood) {
+ FORALLfacet_(facetlist) {
+ if (facet->good && facet->normal) {
+ zinc_(Zdistgood);
+ qh_distplane (qh GOODpointp, facet, &dist);
+ if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
+ facet->good= False;
+ numgood--;
+ }
+ }
+ }
+ }
+ if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
+ FORALLfacet_(facetlist) {
+ if (facet->good && facet->normal) {
+ if (!qh_inthresholds (facet->normal, &angle)) {
+ facet->good= False;
+ numgood--;
+ if (angle < bestangle) {
+ bestangle= angle;
+ bestfacet= facet;
+ }
+ }
+ }
+ }
+ if (!numgood && (!goodhorizon || qh GOODclosest)) {
+ if (qh GOODclosest) {
+ if (qh GOODclosest->visible)
+ qh GOODclosest= NULL;
+ else {
+ qh_inthresholds (qh GOODclosest->normal, &angle);
+ if (angle < bestangle)
+ bestfacet= qh GOODclosest;
+ }
+ }
+ if (bestfacet && bestfacet != qh GOODclosest) {
+ if (qh GOODclosest)
+ qh GOODclosest->good= False;
+ qh GOODclosest= bestfacet;
+ bestfacet->good= True;
+ numgood++;
+ trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n",
+ bestfacet->id, bestangle));
+ return numgood;
+ }
+ }else if (qh GOODclosest) { /* numgood > 0 */
+ qh GOODclosest->good= False;
+ qh GOODclosest= NULL;
+ }
+ }
+ zadd_(Zgoodfacet, numgood);
+ trace2((qh ferr, "qh_findgood: found %d good facets with %d good horizon\n",
+ numgood, goodhorizon));
+ if (!numgood && qh GOODvertex>0 && !qh MERGING)
+ return goodhorizon;
+ return numgood;
+} /* findgood */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="findgood_all">-</a>
+
+ qh_findgood_all( facetlist )
+ apply other constraints for good facets (used by qh.PRINTgood)
+ if qh.GOODvertex
+ facet includes (>0) or doesn't include (<0) point as vertex
+ if last good facet and ONLYgood, prints warning and continues
+ if qh.SPLITthresholds
+ facet->normal matches threshold, or if none, the closest one
+ calls qh_findgood
+ nop if good not used
+
+ returns:
+ clears facet->good if not good
+ sets qh.num_good
+
+ notes:
+ this is like qh_findgood but more restrictive
+
+ design:
+ uses qh_findgood to mark good facets
+ marks facets for qh.GOODvertex
+ marks facets for qh.SPLITthreholds
+*/
+void qh_findgood_all (facetT *facetlist) {
+ facetT *facet, *bestfacet=NULL;
+ realT angle, bestangle= REALmax;
+ int numgood=0, startgood;
+
+ if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
+ && !qh SPLITthresholds)
+ return;
+ if (!qh ONLYgood)
+ qh_findgood (qh facet_list, 0);
+ FORALLfacet_(facetlist) {
+ if (facet->good)
+ numgood++;
+ }
+ if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
+ FORALLfacet_(facetlist) {
+ if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices))) {
+ if (!--numgood) {
+ if (qh ONLYgood) {
+ fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d. Ignored.\n",
+ qh_pointid(qh GOODvertexp), facet->id);
+ return;
+ }else if (qh GOODvertex > 0)
+ fprintf (qh ferr, "qhull warning: point p%d is not a vertex ('QV%d').\n",
+ qh GOODvertex-1, qh GOODvertex-1);
+ else
+ fprintf (qh ferr, "qhull warning: point p%d is a vertex for every facet ('QV-%d').\n",
+ -qh GOODvertex - 1, -qh GOODvertex - 1);
+ }
+ facet->good= False;
+ }
+ }
+ }
+ startgood= numgood;
+ if (qh SPLITthresholds) {
+ FORALLfacet_(facetlist) {
+ if (facet->good) {
+ if (!qh_inthresholds (facet->normal, &angle)) {
+ facet->good= False;
+ numgood--;
+ if (angle < bestangle) {
+ bestangle= angle;
+ bestfacet= facet;
+ }
+ }
+ }
+ }
+ if (!numgood && bestfacet) {
+ bestfacet->good= True;
+ numgood++;
+ trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n",
+ bestfacet->id, bestangle));
+ return;
+ }
+ }
+ qh num_good= numgood;
+ trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n",
+ numgood, startgood));
+} /* findgood_all */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="furthestnext">-</a>
+
+ qh_furthestnext()
+ set qh.facet_next to facet with furthest of all furthest points
+ searches all facets on qh.facet_list
+
+ notes:
+ this may help avoid precision problems
+*/
+void qh_furthestnext (void /* qh facet_list */) {
+ facetT *facet, *bestfacet= NULL;
+ realT dist, bestdist= -REALmax;
+
+ FORALLfacets {
+ if (facet->outsideset) {
+#if qh_COMPUTEfurthest
+ pointT *furthest;
+ furthest= (pointT*)qh_setlast (facet->outsideset);
+ zinc_(Zcomputefurthest);
+ qh_distplane (furthest, facet, &dist);
+#else
+ dist= facet->furthestdist;
+#endif
+ if (dist > bestdist) {
+ bestfacet= facet;
+ bestdist= dist;
+ }
+ }
+ }
+ if (bestfacet) {
+ qh_removefacet (bestfacet);
+ qh_prependfacet (bestfacet, &qh facet_next);
+ trace1((qh ferr, "qh_furthestnext: made f%d next facet (dist %.2g)\n",
+ bestfacet->id, bestdist));
+ }
+} /* furthestnext */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="furthestout">-</a>
+
+ qh_furthestout( facet )
+ make furthest outside point the last point of outsideset
+
+ returns:
+ updates facet->outsideset
+ clears facet->notfurthest
+ sets facet->furthestdist
+
+ design:
+ determine best point of outsideset
+ make it the last point of outsideset
+*/
+void qh_furthestout (facetT *facet) {
+ pointT *point, **pointp, *bestpoint= NULL;
+ realT dist, bestdist= -REALmax;
+
+ FOREACHpoint_(facet->outsideset) {
+ qh_distplane (point, facet, &dist);
+ zinc_(Zcomputefurthest);
+ if (dist > bestdist) {
+ bestpoint= point;
+ bestdist= dist;
+ }
+ }
+ if (bestpoint) {
+ qh_setdel (facet->outsideset, point);
+ qh_setappend (&facet->outsideset, point);
+#if !qh_COMPUTEfurthest
+ facet->furthestdist= bestdist;
+#endif
+ }
+ facet->notfurthest= False;
+ trace3((qh ferr, "qh_furthestout: p%d is furthest outside point of f%d\n",
+ qh_pointid (point), facet->id));
+} /* furthestout */
+
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="infiniteloop">-</a>
+
+ qh_infiniteloop( facet )
+ report infinite loop error due to facet
+*/
+void qh_infiniteloop (facetT *facet) {
+
+ fprintf (qh ferr, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
+ qh_errexit (qh_ERRqhull, facet, NULL);
+} /* qh_infiniteloop */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="initbuild">-</a>
+
+ qh_initbuild()
+ initialize hull and outside sets with point array
+ qh.FIRSTpoint/qh.NUMpoints is point array
+ if qh.GOODpoint
+ adds qh.GOODpoint to initial hull
+
+ returns:
+ qh_facetlist with initial hull
+ points partioned into outside sets, coplanar sets, or inside
+ initializes qh.GOODpointp, qh.GOODvertexp,
+
+ design:
+ initialize global variables used during qh_buildhull
+ determine precision constants and points with max/min coordinate values
+ if qh.SCALElast, scale last coordinate (for 'd')
+ build initial simplex
+ partition input points into facets of initial simplex
+ set up lists
+ if qh.ONLYgood
+ check consistency
+ add qh.GOODvertex if defined
+*/
+void qh_initbuild( void) {
+ setT *maxpoints, *vertices;
+ facetT *facet;
+ int i, numpart;
+ realT dist;
+ boolT isoutside;
+
+ qh furthest_id= -1;
+ qh lastreport= 0;
+ qh facet_id= qh vertex_id= qh ridge_id= 0;
+ qh visit_id= qh vertex_visit= 0;
+ qh maxoutdone= False;
+
+ if (qh GOODpoint > 0)
+ qh GOODpointp= qh_point (qh GOODpoint-1);
+ else if (qh GOODpoint < 0)
+ qh GOODpointp= qh_point (-qh GOODpoint-1);
+ if (qh GOODvertex > 0)
+ qh GOODvertexp= qh_point (qh GOODvertex-1);
+ else if (qh GOODvertex < 0)
+ qh GOODvertexp= qh_point (-qh GOODvertex-1);
+ if ((qh GOODpoint
+ && (qh GOODpointp < qh first_point /* also catches !GOODpointp */
+ || qh GOODpointp > qh_point (qh num_points-1)))
+ || (qh GOODvertex
+ && (qh GOODvertexp < qh first_point /* also catches !GOODvertexp */
+ || qh GOODvertexp > qh_point (qh num_points-1)))) {
+ fprintf (qh ferr, "qhull input error: either QGn or QVn point is > p%d\n",
+ qh num_points-1);
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
+ if (qh SCALElast)
+ qh_scalelast (qh first_point, qh num_points, qh hull_dim,
+ qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
+ qh_detroundoff();
+ if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
+ && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
+ for (i= qh_PRINTEND; i--; ) {
+ if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
+ && !qh GOODthreshold && !qh SPLITthresholds)
+ break; /* in this case, don't set upper_threshold */
+ }
+ if (i < 0) {
+ if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
+ qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
+ qh GOODthreshold= True;
+ }else {
+ qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
+ if (!qh GOODthreshold)
+ qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
+ /* qh_initqhull_globals errors if Qg without Pdk/etc. */
+ }
+ }
+ }
+ vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
+ qh_initialhull (vertices); /* initial qh facet_list */
+ qh_partitionall (vertices, qh first_point, qh num_points);
+ if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
+ if (qh TRACElevel || qh IStracing)
+ fprintf (qh ferr, "\nTrace level %d for %s | %s\n",
+ qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
+ fprintf (qh ferr, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
+ }
+ qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+ qh facet_next= qh facet_list;
+ qh_furthestnext (/* qh facet_list */);
+ if (qh PREmerge) {
+ qh cos_max= qh premerge_cos;
+ qh centrum_radius= qh premerge_centrum;
+ }
+ if (qh ONLYgood) {
+ if (qh GOODvertex > 0 && qh MERGING) {
+ fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (!(qh GOODthreshold || qh GOODpoint
+ || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
+ fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\
+good point (QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (qh GOODvertex > 0 && !qh MERGING /* matches qh_partitionall */
+ && !qh_isvertex (qh GOODvertexp, vertices)) {
+ facet= qh_findbestnew (qh GOODvertexp, qh facet_list,
+ &dist, !qh_ALL, &isoutside, &numpart);
+ zadd_(Zdistgood, numpart);
+ if (!isoutside) {
+ fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex. It can not be made a vertex.\n",
+ qh_pointid(qh GOODvertexp));
+ qh_errexit (qh_ERRinput, NULL, NULL);
+ }
+ if (!qh_addpoint (qh GOODvertexp, facet, False)) {
+ qh_settempfree(&vertices);
+ qh_settempfree(&maxpoints);
+ return;
+ }
+ }
+ qh_findgood (qh facet_list, 0);
+ }
+ qh_settempfree(&vertices);
+ qh_settempfree(&maxpoints);
+ trace1((qh ferr, "qh_initbuild: initial hull created and points partitioned\n"));
+} /* initbuild */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="initialhull">-</a>
+
+ qh_initialhull( vertices )
+ constructs the initial hull as a DIM3 simplex of vertices
+
+ design:
+ creates a simplex (initializes lists)
+ determines orientation of simplex
+ sets hyperplanes for facets
+ doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
+ checks for flipped facets and qh.NARROWhull
+ checks the result
+*/
+void qh_initialhull(setT *vertices) {
+ facetT *facet, *firstfacet, *neighbor, **neighborp;
+ realT dist, angle, minangle= REALmax;
+#ifndef qh_NOtrace
+ int k;
+#endif
+
+ qh_createsimplex(vertices); /* qh facet_list */
+ qh_resetlists (False, qh_RESETvisible);
+ qh facet_next= qh facet_list; /* advance facet when processed */
+ qh interior_point= qh_getcenter(vertices);
+ firstfacet= qh facet_list;
+ qh_setfacetplane(firstfacet);
+ zinc_(Znumvisibility); /* needs to be in printsummary */
+ qh_distplane(qh interior_point, firstfacet, &dist);
+ if (dist > 0) {
+ FORALLfacets
+ facet->toporient ^= True;
+ }
+ FORALLfacets
+ qh_setfacetplane(facet);
+ FORALLfacets {
+ if (!qh_checkflipped (facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
+ trace1((qh ferr, "qh_initialhull: initial orientation incorrect. Correct all facets\n"));
+ facet->flipped= False;
+ FORALLfacets {
+ facet->toporient ^= True;
+ qh_orientoutside (facet);
+ }
+ break;
+ }
+ }
+ FORALLfacets {
+ if (!qh_checkflipped (facet, NULL, !qh_ALL)) { /* can happen with 'R0.1' */
+ qh_precision ("initial facet is coplanar with interior point");
+ fprintf (qh ferr, "qhull precision error: initial facet %d is coplanar with the interior point\n",
+ facet->id);
+ qh_errexit (qh_ERRsingular, facet, NULL);
+ }
+ FOREACHneighbor_(facet) {
+ angle= qh_getangle (facet->normal, neighbor->normal);
+ minimize_( minangle, angle);
+ }
+ }
+ if (minangle < qh_MAXnarrow && !qh NOnarrow) {
+ realT diff= 1.0 + minangle;
+
+ qh NARROWhull= True;
+ qh_option ("_narrow-hull", NULL, &diff);
+ if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
+ fprintf (qh ferr, "qhull precision warning: \n\
+The initial hull is narrow (cosine of min. angle is %.16f).\n\
+A coplanar point may lead to a wide facet. Options 'QbB' (scale to unit box)\n\
+or 'Qbb' (scale last coordinate) may remove this warning. Use 'Pp' to skip\n\
+this warning. See 'Limitations' in qh-impre.htm.\n",
+ -minangle); /* convert from angle between normals to angle between facets */
+ }
+ zzval_(Zprocessed)= qh hull_dim+1;
+ qh_checkpolygon (qh facet_list);
+ qh_checkconvex(qh facet_list, qh_DATAfault);
+#ifndef qh_NOtrace
+ if (qh IStracing >= 1) {
+ fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:");
+ for (k=0; k < qh hull_dim; k++)
+ fprintf (qh ferr, " %6.4g", qh interior_point[k]);
+ fprintf (qh ferr, "\n");
+ }
+#endif
+} /* initialhull */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="initialvertices">-</a>
+
+ qh_initialvertices( dim, maxpoints, points, numpoints )
+ determines a non-singular set of initial vertices
+ maxpoints may include duplicate points
+
+ returns:
+ temporary set of dim+1 vertices in descending order by vertex id
+ if qh.RANDOMoutside && !qh.ALLpoints
+ picks random points
+ if dim >= qh_INITIALmax,
+ uses min/max x and max points with non-zero determinants
+
+ notes:
+ unless qh.ALLpoints,
+ uses maxpoints as long as determinate is non-zero
+*/
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
+ pointT *point, **pointp;
+ setT *vertices, *simplex, *tested;
+ realT randr;
+ int index, point_i, point_n, k;
+ boolT nearzero= False;
+
+ vertices= qh_settemp (dim + 1);
+ simplex= qh_settemp (dim+1);
+ if (qh ALLpoints)
+ qh_maxsimplex (dim, NULL, points, numpoints, &simplex);
+ else if (qh RANDOMoutside) {
+ while (qh_setsize (simplex) != dim+1) {
+ randr= qh_RANDOMint;
+ randr= randr/(qh_RANDOMmax+1);
+ index= (int)floor(qh num_points * randr);
+ while (qh_setin (simplex, qh_point (index))) {
+ index++; /* in case qh_RANDOMint always returns the same value */
+ index= index < qh num_points ? index : 0;
+ }
+ qh_setappend (&simplex, qh_point (index));
+ }
+ }else if (qh hull_dim >= qh_INITIALmax) {
+ tested= qh_settemp (dim+1);
+ qh_setappend (&simplex, SETfirst_(maxpoints)); /* max and min X coord */
+ qh_setappend (&simplex, SETsecond_(maxpoints));
+ qh_maxsimplex (fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
+ k= qh_setsize (simplex);
+ FOREACHpoint_i_(maxpoints) {
+ if (point_i & 0x1) { /* first pick up max. coord. points */
+ if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+ qh_detsimplex(point, simplex, k, &nearzero);
+ if (nearzero)
+ qh_setappend (&tested, point);
+ else {
+ qh_setappend (&simplex, point);
+ if (++k == dim) /* use search for last point */
+ break;
+ }
+ }
+ }
+ }
+ while (k != dim && (point= (pointT*)qh_setdellast (maxpoints))) {
+ if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+ qh_detsimplex (point, simplex, k, &nearzero);
+ if (nearzero)
+ qh_setappend (&tested, point);
+ else {
+ qh_setappend (&simplex, point);
+ k++;
+ }
+ }
+ }
+ index= 0;
+ while (k != dim && (point= qh_point (index++))) {
+ if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+ qh_detsimplex (point, simplex, k, &nearzero);
+ if (!nearzero){
+ qh_setappend (&simplex, point);
+ k++;
+ }
+ }
+ }
+ qh_settempfree (&tested);
+ qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
+ }else
+ qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
+ FOREACHpoint_(simplex)
+ qh_setaddnth (&vertices, 0, qh_newvertex(point)); /* descending order */
+ qh_settempfree (&simplex);
+ return vertices;
+} /* initialvertices */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="isvertex">-</a>
+
+ qh_isvertex( )
+ returns vertex if point is in vertex set, else returns NULL
+
+ notes:
+ for qh.GOODvertex
+*/
+vertexT *qh_isvertex (pointT *point, setT *vertices) {
+ vertexT *vertex, **vertexp;
+
+ FOREACHvertex_(vertices) {
+ if (vertex->point == point)
+ return vertex;
+ }
+ return NULL;
+} /* isvertex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="makenewfacets">-</a>
+
+ qh_makenewfacets( point )
+ make new facets from point and qh.visible_list
+
+ returns:
+ qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
+ qh.newvertex_list= list of vertices in new facets with ->newlist set
+
+ if (qh.ONLYgood)
+ newfacets reference horizon facets, but not vice versa
+ ridges reference non-simplicial horizon ridges, but not vice versa
+ does not change existing facets
+ else
+ sets qh.NEWfacets
+ new facets attached to horizon facets and ridges
+ for visible facets,
+ visible->r.replace is corresponding new facet
+
+ see also:
+ qh_makenewplanes() -- make hyperplanes for facets
+ qh_attachnewfacets() -- attachnewfacets if not done here (qh ONLYgood)
+ qh_matchnewfacets() -- match up neighbors
+ qh_updatevertices() -- update vertex neighbors and delvertices
+ qh_deletevisible() -- delete visible facets
+ qh_checkpolygon() --check the result
+ qh_triangulate() -- triangulate a non-simplicial facet
+
+ design:
+ for each visible facet
+ make new facets to its horizon facets
+ update its f.replace
+ clear its neighbor set
+*/
+vertexT *qh_makenewfacets (pointT *point /*visible_list*/) {
+ facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
+ vertexT *apex;
+ int numnew=0;
+
+ qh newfacet_list= qh facet_tail;
+ qh newvertex_list= qh vertex_tail;
+ apex= qh_newvertex(point);
+ qh_appendvertex (apex);
+ qh visit_id++;
+ if (!qh ONLYgood)
+ qh NEWfacets= True;
+ FORALLvisible_facets {
+ FOREACHneighbor_(visible)
+ neighbor->seen= False;
+ if (visible->ridges) {
+ visible->visitid= qh visit_id;
+ newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew);
+ }
+ if (visible->simplicial)
+ newfacet= qh_makenew_simplicial (visible, apex, &numnew);
+ if (!qh ONLYgood) {
+ if (newfacet2) /* newfacet is null if all ridges defined */
+ newfacet= newfacet2;
+ if (newfacet)
+ visible->f.replace= newfacet;
+ else
+ zinc_(Zinsidevisible);
+ SETfirst_(visible->neighbors)= NULL;
+ }
+ }
+ trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
+ numnew, qh_pointid(point)));
+ if (qh IStracing >= 4)
+ qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
+ return apex;
+} /* makenewfacets */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="matchduplicates">-</a>
+
+ qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
+ match duplicate ridges in qh.hash_table for atfacet/atskip
+ duplicates marked with ->dupridge and qh_DUPLICATEridge
+
+ returns:
+ picks match with worst merge (min distance apart)
+ updates hashcount
+
+ see also:
+ qh_matchneighbor
+
+ notes:
+
+ design:
+ compute hash value for atfacet and atskip
+ repeat twice -- once to make best matches, once to match the rest
+ for each possible facet in qh.hash_table
+ if it is a matching facet and pass 2
+ make match
+ unless tricoplanar, mark match for merging (qh_MERGEridge)
+ [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
+ if it is a matching facet and pass 1
+ test if this is a better match
+ if pass 1,
+ make best match (it will not be merged)
+*/
+#ifndef qh_NOmerge
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+ boolT same, ismatch;
+ int hash, scan;
+ facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
+ int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
+ realT maxdist= -REALmax, mindist, dist2, low, high;
+
+ hash= (int)qh_gethash (hashsize, atfacet->vertices, qh hull_dim, 1,
+ SETelem_(atfacet->vertices, atskip));
+ trace2((qh ferr, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
+ atfacet->id, atskip, hash, *hashcount));
+ for (makematch= 0; makematch < 2; makematch++) {
+ qh visit_id++;
+ for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
+ zinc_(Zhashlookup);
+ nextfacet= NULL;
+ newfacet->visitid= qh visit_id;
+ for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+ scan= (++scan >= hashsize ? 0 : scan)) {
+ if (!facet->dupridge || facet->visitid == qh visit_id)
+ continue;
+ zinc_(Zhashtests);
+ if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+ ismatch= (same == (newfacet->toporient ^ facet->toporient));
+ if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
+ if (!makematch) {
+ fprintf (qh ferr, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
+ facet->id, skip, newfacet->id, newskip, hash);
+ qh_errexit2 (qh_ERRqhull, facet, newfacet);
+ }
+ }else if (ismatch && makematch) {
+ if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+ SETelem_(facet->neighbors, skip)= newfacet;
+ if (newfacet->tricoplanar)
+ SETelem_(newfacet->neighbors, newskip)= facet;
+ else
+ SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
+ *hashcount -= 2; /* removed two unmatched facets */
+ trace4((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
+ facet->id, skip, newfacet->id, newskip));
+ }
+ }else if (ismatch) {
+ mindist= qh_getdistance (facet, newfacet, &low, &high);
+ dist2= qh_getdistance (newfacet, facet, &low, &high);
+ minimize_(mindist, dist2);
+ if (mindist > maxdist) {
+ maxdist= mindist;
+ maxmatch= facet;
+ maxskip= skip;
+ maxmatch2= newfacet;
+ maxskip2= newskip;
+ }
+ trace3((qh ferr, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
+ facet->id, skip, newfacet->id, newskip, mindist,
+ maxmatch->id, maxmatch2->id));
+ }else { /* !ismatch */
+ nextfacet= facet;
+ nextskip= skip;
+ }
+ }
+ if (makematch && !facet
+ && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
+ fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
+ newfacet->id, newskip, hash);
+ qh_errexit (qh_ERRqhull, newfacet, NULL);
+ }
+ }
+ } /* end of for each new facet at hash */
+ if (!makematch) {
+ if (!maxmatch) {
+ fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
+ atfacet->id, atskip, hash);
+ qh_errexit (qh_ERRqhull, atfacet, NULL);
+ }
+ SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
+ SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
+ *hashcount -= 2; /* removed two unmatched facets */
+ zzinc_(Zmultiridge);
+ trace0((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
+ maxmatch->id, maxskip, maxmatch2->id, maxskip2));
+ qh_precision ("ridge with multiple neighbors");
+ if (qh IStracing >= 4)
+ qh_errprint ("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
+ }
+ }
+} /* matchduplicates */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="nearcoplanar">-</a>
+
+ qh_nearcoplanar()
+ for all facets, remove near-inside points from facet->coplanarset</li>
+ coplanar points defined by innerplane from qh_outerinner()
+
+ returns:
+ if qh KEEPcoplanar && !qh KEEPinside
+ facet->coplanarset only contains coplanar points
+ if qh.JOGGLEmax
+ drops inner plane by another qh.JOGGLEmax diagonal since a
+ vertex could shift out while a coplanar point shifts in
+
+ notes:
+ used for qh.PREmerge and qh.JOGGLEmax
+ must agree with computation of qh.NEARcoplanar in qh_detroundoff()
+ design:
+ if not keeping coplanar or inside points
+ free all coplanar sets
+ else if not keeping both coplanar and inside points
+ remove !coplanar or !inside points from coplanar sets
+*/
+void qh_nearcoplanar ( void /* qh.facet_list */) {
+ facetT *facet;
+ pointT *point, **pointp;
+ int numpart;
+ realT dist, innerplane;
+
+ if (!qh KEEPcoplanar && !qh KEEPinside) {
+ FORALLfacets {
+ if (facet->coplanarset)
+ qh_setfree( &facet->coplanarset);
+ }
+ }else if (!qh KEEPcoplanar || !qh KEEPinside) {
+ qh_outerinner (NULL, NULL, &innerplane);
+ if (qh JOGGLEmax < REALmax/2)
+ innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
+ numpart= 0;
+ FORALLfacets {
+ if (facet->coplanarset) {
+ FOREACHpoint_(facet->coplanarset) {
+ numpart++;
+ qh_distplane (point, facet, &dist);
+ if (dist < innerplane) {
+ if (!qh KEEPinside)
+ SETref_(point)= NULL;
+ }else if (!qh KEEPcoplanar)
+ SETref_(point)= NULL;
+ }
+ qh_setcompact (facet->coplanarset);
+ }
+ }
+ zzadd_(Zcheckpart, numpart);
+ }
+} /* nearcoplanar */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="nearvertex">-</a>
+
+ qh_nearvertex( facet, point, bestdist )
+ return nearest vertex in facet to point
+
+ returns:
+ vertex and its distance
+
+ notes:
+ if qh.DELAUNAY
+ distance is measured in the input set
+ searches neighboring tricoplanar facets (requires vertexneighbors)
+ Slow implementation. Recomputes vertex set for each point.
+ The vertex set could be stored in the qh.keepcentrum facet.
+*/
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp) {
+ realT bestdist= REALmax, dist;
+ vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
+ coordT *center;
+ facetT *neighbor, **neighborp;
+ setT *vertices;
+ int dim= qh hull_dim;
+
+ if (qh DELAUNAY)
+ dim--;
+ if (facet->tricoplanar) {
+ if (!qh VERTEXneighbors || !facet->center) {
+ fprintf(qh ferr, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
+ qh_errexit(qh_ERRqhull, NULL, NULL);
+ }
+ vertices= qh_settemp (qh TEMPsize);
+ apex= SETfirst_(facet->vertices);
+ center= facet->center;
+ FOREACHneighbor_(apex) {
+ if (neighbor->center == center) {
+ FOREACHvertex_(neighbor->vertices)
+ qh_setappend(&vertices, vertex);
+ }
+ }
+ }else
+ vertices= facet->vertices;
+ FOREACHvertex_(vertices) {
+ dist= qh_pointdist (vertex->point, point, -dim);
+ if (dist < bestdist) {
+ bestdist= dist;
+ bestvertex= vertex;
+ }
+ }
+ if (facet->tricoplanar)
+ qh_settempfree (&vertices);
+ *bestdistp= sqrt (bestdist);
+ return bestvertex;
+} /* nearvertex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="newhashtable">-</a>
+
+ qh_newhashtable( newsize )
+ returns size of qh.hash_table of at least newsize slots
+
+ notes:
+ assumes qh.hash_table is NULL
+ qh_HASHfactor determines the number of extra slots
+ size is not divisible by 2, 3, or 5
+*/
+int qh_newhashtable(int newsize) {
+ int size;
+
+ size= ((newsize+1)*qh_HASHfactor) | 0x1; /* odd number */
+ while (True) {
+ if ((size%3) && (size%5))
+ break;
+ size += 2;
+ /* loop terminates because there is an infinite number of primes */
+ }
+ qh hash_table= qh_setnew (size);
+ qh_setzero (qh hash_table, 0, size);
+ return size;
+} /* newhashtable */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="newvertex">-</a>
+
+ qh_newvertex( point )
+ returns a new vertex for point
+*/
+vertexT *qh_newvertex(pointT *point) {
+ vertexT *vertex;
+
+ zinc_(Ztotvertices);
+ vertex= (vertexT *)qh_memalloc(sizeof(vertexT));
+ memset ((char *) vertex, 0, sizeof (vertexT));
+ if (qh vertex_id == 0xFFFFFF) {
+ fprintf(qh ferr, "qhull input error: more than %d vertices. ID field overflows and two vertices\n\
+may have the same identifier. Vertices not sorted correctly.\n", 0xFFFFFF);
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ if (qh vertex_id == qh tracevertex_id)
+ qh tracevertex= vertex;
+ vertex->id= qh vertex_id++;
+ vertex->point= point;
+ trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point),
+ vertex->id));
+ return (vertex);
+} /* newvertex */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="nextridge3d">-</a>
+
+ qh_nextridge3d( atridge, facet, vertex )
+ return next ridge and vertex for a 3d facet
+
+ notes:
+ in qh_ORIENTclock order
+ this is a O(n^2) implementation to trace all ridges
+ be sure to stop on any 2nd visit
+
+ design:
+ for each ridge
+ exit if it is the ridge after atridge
+*/
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+ vertexT *atvertex, *vertex, *othervertex;
+ ridgeT *ridge, **ridgep;
+
+ if ((atridge->top == facet) ^ qh_ORIENTclock)
+ atvertex= SETsecondt_(atridge->vertices, vertexT);
+ else
+ atvertex= SETfirstt_(atridge->vertices, vertexT);
+ FOREACHridge_(facet->ridges) {
+ if (ridge == atridge)
+ continue;
+ if ((ridge->top == facet) ^ qh_ORIENTclock) {
+ othervertex= SETsecondt_(ridge->vertices, vertexT);
+ vertex= SETfirstt_(ridge->vertices, vertexT);
+ }else {
+ vertex= SETsecondt_(ridge->vertices, vertexT);
+ othervertex= SETfirstt_(ridge->vertices, vertexT);
+ }
+ if (vertex == atvertex) {
+ if (vertexp)
+ *vertexp= othervertex;
+ return ridge;
+ }
+ }
+ return NULL;
+} /* nextridge3d */
+#else /* qh_NOmerge */
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+}
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+
+ return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="outcoplanar">-</a>
+
+ qh_outcoplanar()
+ move points from all facets' outsidesets to their coplanarsets
+
+ notes:
+ for post-processing under qh.NARROWhull
+
+ design:
+ for each facet
+ for each outside point for facet
+ partition point into coplanar set
+*/
+void qh_outcoplanar (void /* facet_list */) {
+ pointT *point, **pointp;
+ facetT *facet;
+ realT dist;
+
+ trace1((qh ferr, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
+ FORALLfacets {
+ FOREACHpoint_(facet->outsideset) {
+ qh num_outside--;
+ if (qh KEEPcoplanar || qh KEEPnearinside) {
+ qh_distplane (point, facet, &dist);
+ zinc_(Zpartition);
+ qh_partitioncoplanar (point, facet, &dist);
+ }
+ }
+ qh_setfree (&facet->outsideset);
+ }
+} /* outcoplanar */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="point">-</a>
+
+ qh_point( id )
+ return point for a point id, or NULL if unknown
+
+ alternative code:
+ return ((pointT *)((unsigned long)qh.first_point
+ + (unsigned long)((id)*qh.normal_size)));
+*/
+pointT *qh_point (int id) {
+
+ if (id < 0)
+ return NULL;
+ if (id < qh num_points)
+ return qh first_point + id * qh hull_dim;
+ id -= qh num_points;
+ if (id < qh_setsize (qh other_points))
+ return SETelemt_(qh other_points, id, pointT);
+ return NULL;
+} /* point */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="point_add">-</a>
+
+ qh_point_add( set, point, elem )
+ stores elem at set[point.id]
+
+ returns:
+ access function for qh_pointfacet and qh_pointvertex
+
+ notes:
+ checks point.id
+*/
+void qh_point_add (setT *set, pointT *point, void *elem) {
+ int id, size;
+
+ SETreturnsize_(set, size);
+ if ((id= qh_pointid(point)) < 0)
+ fprintf (qh ferr, "qhull internal warning (point_add): unknown point %p id %d\n",
+ point, id);
+ else if (id >= size) {
+ fprintf (qh ferr, "qhull internal errror (point_add): point p%d is out of bounds (%d)\n",
+ id, size);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }else
+ SETelem_(set, id)= elem;
+} /* point_add */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="pointfacet">-</a>
+
+ qh_pointfacet()
+ return temporary set of facet for each point
+ the set is indexed by point id
+
+ notes:
+ vertices assigned to one of the facets
+ coplanarset assigned to the facet
+ outside set assigned to the facet
+ NULL if no facet for point (inside)
+ includes qh.GOODpointp
+
+ access:
+ FOREACHfacet_i_(facets) { ... }
+ SETelem_(facets, i)
+
+ design:
+ for each facet
+ add each vertex
+ add each coplanar point
+ add each outside point
+*/
+setT *qh_pointfacet (void /*qh facet_list*/) {
+ int numpoints= qh num_points + qh_setsize (qh other_points);
+ setT *facets;
+ facetT *facet;
+ vertexT *vertex, **vertexp;
+ pointT *point, **pointp;
+
+ facets= qh_settemp (numpoints);
+ qh_setzero (facets, 0, numpoints);
+ qh vertex_visit++;
+ FORALLfacets {
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ vertex->visitid= qh vertex_visit;
+ qh_point_add (facets, vertex->point, facet);
+ }
+ }
+ FOREACHpoint_(facet->coplanarset)
+ qh_point_add (facets, point, facet);
+ FOREACHpoint_(facet->outsideset)
+ qh_point_add (facets, point, facet);
+ }
+ return facets;
+} /* pointfacet */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="pointvertex">-</a>
+
+ qh_pointvertex( )
+ return temporary set of vertices indexed by point id
+ entry is NULL if no vertex for a point
+ this will include qh.GOODpointp
+
+ access:
+ FOREACHvertex_i_(vertices) { ... }
+ SETelem_(vertices, i)
+*/
+setT *qh_pointvertex (void /*qh facet_list*/) {
+ int numpoints= qh num_points + qh_setsize (qh other_points);
+ setT *vertices;
+ vertexT *vertex;
+
+ vertices= qh_settemp (numpoints);
+ qh_setzero (vertices, 0, numpoints);
+ FORALLvertices
+ qh_point_add (vertices, vertex->point, vertex);
+ return vertices;
+} /* pointvertex */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="prependfacet">-</a>
+
+ qh_prependfacet( facet, facetlist )
+ prepend facet to the start of a facetlist
+
+ returns:
+ increments qh.numfacets
+ updates facetlist, qh.facet_list, facet_next
+
+ notes:
+ be careful of prepending since it can lose a pointer.
+ e.g., can lose _next by deleting and then prepending before _next
+*/
+void qh_prependfacet(facetT *facet, facetT **facetlist) {
+ facetT *prevfacet, *list;
+
+
+ trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n",
+ facet->id, getid_(*facetlist)));
+ if (!*facetlist)
+ (*facetlist)= qh facet_tail;
+ list= *facetlist;
+ prevfacet= list->previous;
+ facet->previous= prevfacet;
+ if (prevfacet)
+ prevfacet->next= facet;
+ list->previous= facet;
+ facet->next= *facetlist;
+ if (qh facet_list == list) /* this may change *facetlist */
+ qh facet_list= facet;
+ if (qh facet_next == list)
+ qh facet_next= facet;
+ *facetlist= facet;
+ qh num_facets++;
+} /* prependfacet */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="printhashtable">-</a>
+
+ qh_printhashtable( fp )
+ print hash table to fp
+
+ notes:
+ not in I/O to avoid bringing io.c in
+
+ design:
+ for each hash entry
+ if defined
+ if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
+ print entry and neighbors
+*/
+void qh_printhashtable(FILE *fp) {
+ facetT *facet, *neighbor;
+ int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
+ vertexT *vertex, **vertexp;
+
+ FOREACHfacet_i_(qh hash_table) {
+ if (facet) {
+ FOREACHneighbor_i_(facet) {
+ if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
+ break;
+ }
+ if (neighbor_i == neighbor_n)
+ continue;
+ fprintf (fp, "hash %d f%d ", facet_i, facet->id);
+ FOREACHvertex_(facet->vertices)
+ fprintf (fp, "v%d ", vertex->id);
+ fprintf (fp, "\n neighbors:");
+ FOREACHneighbor_i_(facet) {
+ if (neighbor == qh_MERGEridge)
+ id= -3;
+ else if (neighbor == qh_DUPLICATEridge)
+ id= -2;
+ else
+ id= getid_(neighbor);
+ fprintf (fp, " %d", id);
+ }
+ fprintf (fp, "\n");
+ }
+ }
+} /* printhashtable */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="printlists">-</a>
+
+ qh_printlists( fp )
+ print out facet and vertex list for debugging (without 'f/v' tags)
+*/
+void qh_printlists (void) {
+ facetT *facet;
+ vertexT *vertex;
+ int count= 0;
+
+ fprintf (qh ferr, "qh_printlists: facets:");
+ FORALLfacets {
+ if (++count % 100 == 0)
+ fprintf (qh ferr, "\n ");
+ fprintf (qh ferr, " %d", facet->id);
+ }
+ fprintf (qh ferr, "\n new facets %d visible facets %d next facet for qh_addpoint %d\n vertices (new %d):",
+ getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
+ getid_(qh newvertex_list));
+ count = 0;
+ FORALLvertices {
+ if (++count % 100 == 0)
+ fprintf (qh ferr, "\n ");
+ fprintf (qh ferr, " %d", vertex->id);
+ }
+ fprintf (qh ferr, "\n");
+} /* printlists */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="resetlists">-</a>
+
+ qh_resetlists( stats, qh_RESETvisible )
+ reset newvertex_list, newfacet_list, visible_list
+ if stats,
+ maintains statistics
+
+ returns:
+ visible_list is empty if qh_deletevisible was called
+*/
+void qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
+ vertexT *vertex;
+ facetT *newfacet, *visible;
+ int totnew=0, totver=0;
+
+ if (stats) {
+ FORALLvertex_(qh newvertex_list)
+ totver++;
+ FORALLnew_facets
+ totnew++;
+ zadd_(Zvisvertextot, totver);
+ zmax_(Zvisvertexmax, totver);
+ zadd_(Znewfacettot, totnew);
+ zmax_(Znewfacetmax, totnew);
+ }
+ FORALLvertex_(qh newvertex_list)
+ vertex->newlist= False;
+ qh newvertex_list= NULL;
+ FORALLnew_facets
+ newfacet->newfacet= False;
+ qh newfacet_list= NULL;
+ if (resetVisible) {
+ FORALLvisible_facets {
+ visible->f.replace= NULL;
+ visible->visible= False;
+ }
+ qh num_visible= 0;
+ }
+ qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
+ qh NEWfacets= False;
+} /* resetlists */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="setvoronoi_all">-</a>
+
+ qh_setvoronoi_all()
+ compute Voronoi centers for all facets
+ includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
+
+ returns:
+ facet->center is the Voronoi center
+
+ notes:
+ this is unused/untested code
+ please email bradb@shore.net if this works ok for you
+
+ use:
+ FORALLvertices {...} to locate the vertex for a point.
+ FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
+*/
+void qh_setvoronoi_all (void) {
+ facetT *facet;
+
+ qh_clearcenters (qh_ASvoronoi);
+ qh_vertexneighbors();
+
+ FORALLfacets {
+ if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
+ if (!facet->center)
+ facet->center= qh_facetcenter (facet->vertices);
+ }
+ }
+} /* setvoronoi_all */
+
+#ifndef qh_NOmerge
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="triangulate">-</a>
+
+ qh_triangulate()
+ triangulate non-simplicial facets on qh.facet_list,
+ if qh.CENTERtype=qh_ASvoronoi, sets Voronoi centers of non-simplicial facets
+
+ returns:
+ all facets simplicial
+ each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
+
+ notes:
+ call after qh_check_output since may switch to Voronoi centers
+ Output may overwrite ->f.triowner with ->f.area
+*/
+void qh_triangulate (void /*qh facet_list*/) {
+ facetT *facet, *nextfacet, *owner;
+ int onlygood= qh ONLYgood;
+ facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
+ facetT *orig_neighbor= NULL, *otherfacet;
+ vertexT *new_vertex_list= NULL;
+ mergeT *merge;
+ mergeType mergetype;
+ int neighbor_i, neighbor_n;
+
+ trace1((qh ferr, "qh_triangulate: triangulate non-simplicial facets\n"));
+ if (qh hull_dim == 2)
+ return;
+ if (qh VORONOI) { /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
+ qh_clearcenters (qh_ASvoronoi);
+ qh_vertexneighbors();
+ }
+ qh ONLYgood= False; /* for makenew_nonsimplicial */
+ qh visit_id++;
+ qh NEWfacets= True;
+ qh degen_mergeset= qh_settemp (qh TEMPsize);
+ qh newvertex_list= qh vertex_tail;
+ for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
+ nextfacet= facet->next;
+ if (facet->visible || facet->simplicial)
+ continue;
+ /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
+ if (!new_facet_list)
+ new_facet_list= facet; /* will be moved to end */
+ qh_triangulate_facet (facet, &new_vertex_list);
+ }
+ trace2((qh ferr, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
+ for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
+ nextfacet= facet->next;
+ if (facet->visible)
+ continue;
+ if (facet->ridges) {
+ if (qh_setsize(facet->ridges) > 0) {
+ fprintf( qh ferr, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ qh_setfree (&facet->ridges);
+ }
+ if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
+ zinc_(Ztrinull);
+ qh_triangulate_null (facet);
+ }
+ }
+ trace2((qh ferr, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
+ qh visible_list= qh facet_tail;
+ while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
+ facet1= merge->facet1;
+ facet2= merge->facet2;
+ mergetype= merge->type;
+ qh_memfree (merge, sizeof(mergeT));
+ if (mergetype == MRGmirror) {
+ zinc_(Ztrimirror);
+ qh_triangulate_mirror (facet1, facet2);
+ }
+ }
+ qh_settempfree(&qh degen_mergeset);
+ trace2((qh ferr, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
+ qh newvertex_list= new_vertex_list; /* all vertices of new facets */
+ qh visible_list= NULL;
+ qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
+ qh_resetlists (False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
+
+ trace2((qh ferr, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
+ trace2((qh ferr, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
+ FORALLfacet_(new_facet_list) {
+ if (facet->tricoplanar && !facet->visible) {
+ FOREACHneighbor_i_(facet) {
+ if (neighbor_i == 0) { /* first iteration */
+ if (neighbor->tricoplanar)
+ orig_neighbor= neighbor->f.triowner;
+ else
+ orig_neighbor= neighbor;
+ }else {
+ if (neighbor->tricoplanar)
+ otherfacet= neighbor->f.triowner;
+ else
+ otherfacet= neighbor;
+ if (orig_neighbor == otherfacet) {
+ zinc_(Ztridegen);
+ facet->degenerate= True;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ trace2((qh ferr, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
+ owner= NULL;
+ visible= NULL;
+ for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
+ nextfacet= facet->next;
+ if (facet->visible) {
+ if (facet->tricoplanar) { /* a null or mirrored facet */
+ qh_delfacet(facet);
+ qh num_visible--;
+ }else { /* a non-simplicial facet followed by its tricoplanars */
+ if (visible && !owner) {
+ /* RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
+ trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
+ visible->id));
+ qh_delfacet(visible);
+ qh num_visible--;
+ }
+ visible= facet;
+ owner= NULL;
+ }
+ }else if (facet->tricoplanar) {
+ if (facet->f.triowner != visible) {
+ fprintf( qh ferr, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
+ qh_errexit2 (qh_ERRqhull, facet, visible);
+ }
+ if (owner)
+ facet->f.triowner= owner;
+ else if (!facet->degenerate) {
+ owner= facet;
+ nextfacet= visible->next; /* rescan tricoplanar facets with owner */
+ facet->keepcentrum= True; /* one facet owns ->normal, etc. */
+ facet->coplanarset= visible->coplanarset;
+ facet->outsideset= visible->outsideset;
+ visible->coplanarset= NULL;
+ visible->outsideset= NULL;
+ if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
+ visible->center= NULL;
+ visible->normal= NULL;
+ }
+ qh_delfacet(visible);
+ qh num_visible--;
+ }
+ }
+ }
+ if (visible && !owner) {
+ trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
+ visible->id));
+ qh_delfacet(visible);
+ qh num_visible--;
+ }
+ qh NEWfacets= False;
+ qh ONLYgood= onlygood; /* restore value */
+ if (qh CHECKfrequently)
+ qh_checkpolygon (qh facet_list);
+} /* triangulate */
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="triangulate_facet">-</a>
+
+ qh_triangulate_facet (facetA)
+ triangulate a non-simplicial facet
+ if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
+ returns:
+ qh.newfacet_list == simplicial facets
+ facet->tricoplanar set and ->keepcentrum false
+ facet->degenerate set if duplicated apex
+ facet->f.trivisible set to facetA
+ facet->center copied from facetA (created if qh_ASvoronoi)
+ qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
+ facet->normal,offset,maxoutside copied from facetA
+
+ notes:
+ qh_makenew_nonsimplicial uses neighbor->seen for the same
+
+ see also:
+ qh_addpoint() -- add a point
+ qh_makenewfacets() -- construct a cone of facets for a new vertex
+
+ design:
+ if qh_ASvoronoi,
+ compute Voronoi center (facet->center)
+ select first vertex (highest ID to preserve ID ordering of ->vertices)
+ triangulate from vertex to ridges
+ copy facet->center, normal, offset
+ update vertex neighbors
+*/
+void qh_triangulate_facet (facetT *facetA, vertexT **first_vertex) {
+ facetT *newfacet;
+ facetT *neighbor, **neighborp;
+ vertexT *apex;
+ int numnew=0;
+
+ trace3((qh ferr, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
+
+ if (qh IStracing >= 4)
+ qh_printfacet (qh ferr, facetA);
+ FOREACHneighbor_(facetA) {
+ neighbor->seen= False;
+ neighbor->coplanar= False;
+ }
+ if (qh CENTERtype == qh_ASvoronoi && !facetA->center /* matches upperdelaunay in qh_setfacetplane() */
+ && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
+ facetA->center= qh_facetcenter (facetA->vertices);
+ }
+ qh_willdelete (facetA, NULL);
+ qh newfacet_list= qh facet_tail;
+ facetA->visitid= qh visit_id;
+ apex= SETfirst_(facetA->vertices);
+ qh_makenew_nonsimplicial (facetA, apex, &numnew);
+ SETfirst_(facetA->neighbors)= NULL;
+ FORALLnew_facets {
+ newfacet->tricoplanar= True;
+ newfacet->f.trivisible= facetA;
+ newfacet->degenerate= False;
+ newfacet->upperdelaunay= facetA->upperdelaunay;
+ newfacet->good= facetA->good;
+ if (qh TRInormals) {
+ newfacet->keepcentrum= True;
+ newfacet->normal= qh_copypoints (facetA->normal, 1, qh hull_dim);
+ if (qh CENTERtype == qh_AScentrum)
+ newfacet->center= qh_getcentrum (newfacet);
+ else
+ newfacet->center= qh_copypoints (facetA->center, 1, qh hull_dim);
+ }else {
+ newfacet->keepcentrum= False;
+ newfacet->normal= facetA->normal;
+ newfacet->center= facetA->center;
+ }
+ newfacet->offset= facetA->offset;
+#if qh_MAXoutside
+ newfacet->maxoutside= facetA->maxoutside;
+#endif
+ }
+ qh_matchnewfacets(/*qh newfacet_list*/);
+ zinc_(Ztricoplanar);
+ zadd_(Ztricoplanartot, numnew);
+ zmax_(Ztricoplanarmax, numnew);
+ qh visible_list= NULL;
+ if (!(*first_vertex))
+ (*first_vertex)= qh newvertex_list;
+ qh newvertex_list= NULL;
+ qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
+ qh_resetlists (False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
+} /* triangulate_facet */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="triangulate_link">-</a>
+
+ qh_triangulate_link (oldfacetA, facetA, oldfacetB, facetB)
+ relink facetA to facetB via oldfacets
+ returns:
+ adds mirror facets to qh degen_mergeset (4-d and up only)
+ design:
+ if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
+ int errmirror= False;
+
+ trace3((qh ferr, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
+ oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
+ if (qh_setin (facetA->neighbors, facetB)) {
+ if (!qh_setin (facetB->neighbors, facetA))
+ errmirror= True;
+ else
+ qh_appendmergeset (facetA, facetB, MRGmirror, NULL);
+ }else if (qh_setin (facetB->neighbors, facetA))
+ errmirror= True;
+ if (errmirror) {
+ fprintf( qh ferr, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
+ facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
+ qh_errexit2 (qh_ERRqhull, facetA, facetB);
+ }
+ qh_setreplace (facetB->neighbors, oldfacetB, facetA);
+ qh_setreplace (facetA->neighbors, oldfacetA, facetB);
+} /* triangulate_link */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="triangulate_mirror">-</a>
+
+ qh_triangulate_mirror (facetA, facetB)
+ delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
+ a mirrored facet shares the same vertices of a logical ridge
+ design:
+ since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+ if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_mirror (facetT *facetA, facetT *facetB) {
+ facetT *neighbor, *neighborB;
+ int neighbor_i, neighbor_n;
+
+ trace3((qh ferr, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
+ facetA->id, facetB->id));
+ FOREACHneighbor_i_(facetA) {
+ neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
+ if (neighbor == neighborB)
+ continue; /* occurs twice */
+ qh_triangulate_link (facetA, neighbor, facetB, neighborB);
+ }
+ qh_willdelete (facetA, NULL);
+ qh_willdelete (facetB, NULL);
+} /* triangulate_mirror */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="triangulate_null">-</a>
+
+ qh_triangulate_null (facetA)
+ remove null facetA from qh_triangulate_facet()
+ a null facet has vertex #1 (apex) == vertex #2
+ returns:
+ adds facetA to ->visible for deletion after qh_updatevertices
+ qh degen_mergeset contains mirror facets (4-d and up only)
+ design:
+ since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+ if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_null (facetT *facetA) {
+ facetT *neighbor, *otherfacet;
+
+ trace3((qh ferr, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
+ neighbor= SETfirst_(facetA->neighbors);
+ otherfacet= SETsecond_(facetA->neighbors);
+ qh_triangulate_link (facetA, neighbor, facetA, otherfacet);
+ qh_willdelete (facetA, NULL);
+} /* triangulate_null */
+
+#else /* qh_NOmerge */
+void qh_triangulate (void) {
+}
+#endif /* qh_NOmerge */
+
+ /*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="vertexintersect">-</a>
+
+ qh_vertexintersect( vertexsetA, vertexsetB )
+ intersects two vertex sets (inverse id ordered)
+ vertexsetA is a temporary set at the top of qhmem.tempstack
+
+ returns:
+ replaces vertexsetA with the intersection
+
+ notes:
+ could overwrite vertexsetA if currently too slow
+*/
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
+ setT *intersection;
+
+ intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB);
+ qh_settempfree (vertexsetA);
+ *vertexsetA= intersection;
+ qh_settemppush (intersection);
+} /* vertexintersect */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="vertexintersect_new">-</a>
+
+ qh_vertexintersect_new( )
+ intersects two vertex sets (inverse id ordered)
+
+ returns:
+ a new set
+*/
+setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) {
+ setT *intersection= qh_setnew (qh hull_dim - 1);
+ vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
+ vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
+
+ while (*vertexA && *vertexB) {
+ if (*vertexA == *vertexB) {
+ qh_setappend(&intersection, *vertexA);
+ vertexA++; vertexB++;
+ }else {
+ if ((*vertexA)->id > (*vertexB)->id)
+ vertexA++;
+ else
+ vertexB++;
+ }
+ }
+ return intersection;
+} /* vertexintersect_new */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="vertexneighbors">-</a>
+
+ qh_vertexneighbors()
+ for each vertex in qh.facet_list,
+ determine its neighboring facets
+
+ returns:
+ sets qh.VERTEXneighbors
+ nop if qh.VERTEXneighbors already set
+ qh_addpoint() will maintain them
+
+ notes:
+ assumes all vertex->neighbors are NULL
+
+ design:
+ for each facet
+ for each vertex
+ append facet to vertex->neighbors
+*/
+void qh_vertexneighbors (void /*qh facet_list*/) {
+ facetT *facet;
+ vertexT *vertex, **vertexp;
+
+ if (qh VERTEXneighbors)
+ return;
+ trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
+ qh vertex_visit++;
+ FORALLfacets {
+ if (facet->visible)
+ continue;
+ FOREACHvertex_(facet->vertices) {
+ if (vertex->visitid != qh vertex_visit) {
+ vertex->visitid= qh vertex_visit;
+ vertex->neighbors= qh_setnew (qh hull_dim);
+ }
+ qh_setappend (&vertex->neighbors, facet);
+ }
+ }
+ qh VERTEXneighbors= True;
+} /* vertexneighbors */
+
+/*-<a href="qh-poly.htm#TOC"
+ >-------------------------------</a><a name="vertexsubset">-</a>
+
+ qh_vertexsubset( vertexsetA, vertexsetB )
+ returns True if vertexsetA is a subset of vertexsetB
+ assumes vertexsets are sorted
+
+ note:
+ empty set is a subset of any other set
+*/
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
+ vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
+ vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
+
+ while (True) {
+ if (!*vertexA)
+ return True;
+ if (!*vertexB)
+ return False;
+ if ((*vertexA)->id > (*vertexB)->id)
+ return False;
+ if (*vertexA == *vertexB)
+ vertexA++;
+ vertexB++;
+ }
+ return False; /* avoid warnings */
+} /* vertexsubset */
diff --git a/extern/qhull/src/qconvex.c b/extern/qhull/src/qconvex.c
new file mode 100644
index 00000000000..67b78646e50
--- /dev/null
+++ b/extern/qhull/src/qconvex.c
@@ -0,0 +1,334 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qconvex.c
+ compute convex hulls using qhull
+
+ see unix.c for full interface
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+
+#elif __cplusplus
+extern "C" {
+ int isatty (int);
+}
+
+#elif _MSC_VER
+#include <io.h>
+#define isatty _isatty
+
+#else
+int isatty (int); /* returns 1 if stdin is a tty
+ if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt">-</a>
+
+ qh_prompt
+ long prompt for qconvex
+
+ notes:
+ restricted version of qhull.c
+
+ see:
+ concise prompt below
+*/
+
+/* duplicated in qconvex.htm */
+char hidden_options[]=" d v H Qbb Qf Qg Qm Qr Qu Qv Qx Qz TR E V Fp Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qconvex- compute the convex hull\n\
+ http://www.geom.umn.edu/software/qhull %s\n\
+\n\
+input (stdin):\n\
+ first lines: dimension and number of points (or vice-versa).\n\
+ other lines: point coordinates, best if one point per line\n\
+ comments: start with a non-numeric character\n\
+\n\
+options:\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Qc - keep coplanar points with nearest facet\n\
+ Qi - keep interior points with nearest facet\n\
+\n\
+Qhull control options:\n\
+ Qbk:n - scale coord k so that low bound is n\n\
+ QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
+ QbB - scale input to unit cube centered at the origin\n\
+ Qbk:0Bk:0 - remove k-th coordinate from input\n\
+ QJn - randomly joggle input in range [-n,n]\n\
+ QRn - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
+%s%s%s%s"; /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+ Qs - search all points for the initial simplex\n\
+ QGn - good facet if visible from point n, -n for not visible\n\
+ QVn - good facet if it includes point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+ T4 - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+ Tc - check frequently during execution\n\
+ Ts - print statistics\n\
+ Tv - verify result: structure, convexity, and point inclusion\n\
+ Tz - send all output to stdout\n\
+ TFn - report summary when n or more facets created\n\
+ TI file - input data from file, no spaces or single quotes\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+ TPn - turn on tracing when point n added to hull\n\
+ TMn - turn on tracing at merge n\n\
+ TWn - trace merge facets when width > n\n\
+ TVn - stop qhull after adding point n, -n for before (see TCn)\n\
+ TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+ Cn - radius of centrum (roundoff added). Merge facets if non-convex\n\
+ An - cosine of maximum angle. Merge facets if cosine > n or non-convex\n\
+ C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+ Rn - randomly perturb computations by a factor of [1-n,1+n]\n\
+ Un - max distance below plane for a new, coplanar point\n\
+ Wn - min facet width for outside point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+ f - facet dump\n\
+ G - Geomview output (see below)\n\
+ i - vertices incident to each facet\n\
+ m - Mathematica output (2-d and 3-d)\n\
+ n - normals with offsets\n\
+ o - OFF file format (dim, points and facets; Voronoi regions)\n\
+ p - point coordinates \n\
+ s - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+ Fa - area for each facet\n\
+ FA - compute total area and volume for option 's'\n\
+ Fc - count plus coplanar points for each facet\n\
+ use 'Qc' (default) for coplanar and 'Qi' for interior\n\
+ FC - centrum for each facet\n\
+ Fd - use cdd format for input (homogeneous with offset first)\n\
+ FD - use cdd format for numeric output (offset first)\n\
+ FF - facet dump without ridges\n\
+ Fi - inner plane for each facet\n\
+ FI - ID for each facet\n\
+ Fm - merge count for each facet (511 max)\n\
+ Fn - count plus neighboring facets for each facet\n\
+ FN - count plus neighboring facets for each point\n\
+ Fo - outer plane (or max_outside) for each facet\n\
+ FO - options and precision constants\n\
+ FP - nearest vertex for each coplanar point\n\
+ FQ - command used for qconvex\n\
+ Fs - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+ for output: #vertices, #facets,\n\
+ #coplanar points, #non-simplicial facets\n\
+ #real (2), max outer plane, min vertex\n\
+ FS - sizes: #int (0) \n\
+ #real(2) tot area, tot volume\n\
+ Ft - triangulation with centrums for non-simplicial facets (OFF format)\n\
+ Fv - count plus vertices for each facet\n\
+ FV - average of vertices (a feasible point for 'H')\n\
+ Fx - extreme points (in order for 2-d)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview output (2-d, 3-d, and 4-d)\n\
+ Ga - all points as dots\n\
+ Gp - coplanar points and vertices as radii\n\
+ Gv - vertices as spheres\n\
+ Gi - inner planes only\n\
+ Gn - no planes\n\
+ Go - outer planes only\n\
+ Gc - centrums\n\
+ Gh - hyperplane intersections\n\
+ Gr - ridges\n\
+ GDn - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+ PAn - keep n largest facets by area\n\
+ Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+ PDk:n - drop facet if normal[k] >= n\n\
+ Pg - print good facets (needs 'QGn' or 'QVn')\n\
+ PFn - keep facets whose area is at least n\n\
+ PG - print neighbors of good facets\n\
+ PMn - keep n facets with most merges\n\
+ Po - force output. If error, output neighborhood of facet\n\
+ Pp - do not report precision problems\n\
+\n\
+ . - list of all options\n\
+ - - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt2">-</a>
+
+ qh_prompt2
+ synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qconvex- compute the convex hull. Qhull %s\n\
+ input (stdin): dimension, number of points, point coordinates\n\
+ comments start with a non-numeric character\n\
+\n\
+options (qconvex.htm):\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Tv - verify result: structure, convexity, and point inclusion\n\
+ . - concise list of all options\n\
+ - - one-line description of all options\n\
+\n\
+output options (subset):\n\
+ s - summary of results (default)\n\
+ i - vertices incident to each facet\n\
+ n - normals with offsets\n\
+ p - vertex coordinates (includes coplanar points if 'Qc')\n\
+ Fx - extreme points (convex hull vertices)\n\
+ FA - compute total area and volume\n\
+ o - OFF format (dim, n, points, facets)\n\
+ G - Geomview output (2-d, 3-d, and 4-d)\n\
+ m - Mathematica output (2-d and 3-d)\n\
+ QVn - print facets that include point n, -n if not\n\
+ TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+ rbox c D2 | qconvex s n rbox c D2 | qconvex i\n\
+ rbox c D2 | qconvex o rbox 1000 s | qconvex s Tv FA\n\
+ rbox c d D2 | qconvex s Qc Fx rbox y 1000 W0 | qconvex s n\n\
+ rbox y 1000 W0 | qconvex s QJ rbox d G1 D12 | qconvex QR0 FA Pp\n\
+ rbox c D7 | qconvex FA TF1000\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt3">-</a>
+
+ qh_prompt3
+ concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ incidences mathematica normals OFF_format points\n\
+ summary facet_dump\n\
+\n\
+ Farea FArea_total Fcoplanars FCentrums Fd_cdd_in\n\
+ FD_cdd_out FFacet_xridge Finner FIDs Fmerges\n\
+ Fneighbors FNeigh_vertex Fouter FOptions FPoint_near\n\
+ FQhull Fsummary FSize Fvertices FVertex_ave\n\
+ Fxtremes\n\
+\n\
+ Gvertices Gpoints Gall_points Gno_planes Ginner\n\
+ Gcentrums Ghyperplanes Gridges Gouter GDrop_dim\n\
+\n\
+ PArea_keep Pdrop d0:0D0 PFacet_area_keep Pgood PGood_neighbors\n\
+ PMerge_keep Poutput_forced Pprecision_not\n\
+\n\
+ QbBound 0:0.5 QbB_scale_box Qcoplanar QGood_point Qinterior\n\
+ QJoggle Qrandom QRotate Qsearch_1st Qtriangulate\n\
+ QVertex_good\n\
+\n\
+ T4_trace Tcheck_often Tstatistics Tverify Tz_stdout\n\
+ TFacet_log TInput_file TPoint_trace TMerge_trace TOutput_file\n\
+ TWide_trace TVertex_stop TCone_stop\n\
+\n\
+ Angle_max Centrum_size Random_dist Ucoplanar_max Wide_outside\n\
+";
+
+/*-<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="main">-</a>
+
+ main( argc, argv )
+ processes the command line, calls qhull() to do the work, and exits
+
+ design:
+ initializes data structures
+ reads points
+ finishes initialization
+ computes convex hull and other structures
+ checks the result
+ writes the output
+ frees memory
+*/
+int main(int argc, char *argv[]) {
+ int curlong, totlong; /* used !qh_NOmem */
+ int exitcode, numpoints, dim;
+ coordT *points;
+ boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= false;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+
+ if ((argc == 1) && isatty( 0 /*stdin*/)) {
+ fprintf(stdout, qh_prompt2, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompta, qh_VERSION, qh_DEFAULTbox,
+ qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+ exit(qh_ERRnone);
+ }
+ if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompt3, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ qh_init_A (stdin, stdout, stderr, argc, argv); /* sets qh qhull_command */
+ exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+ if (!exitcode) {
+ qh_checkflags (qh qhull_command, hidden_options);
+ qh_initflags (qh qhull_command);
+ points= qh_readpoints (&numpoints, &dim, &ismalloc);
+ if (dim >= 5) {
+ qh_option ("Qxact_merge", NULL, NULL);
+ qh MERGEexact= True; /* 'Qx' always */
+ }
+ qh_init_B (points, numpoints, dim, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ exitcode= qh_ERRnone;
+ }
+ qh NOerrexit= True; /* no more setjmp */
+#ifdef qh_NOmem
+ qh_freeqhull( True);
+#else
+ qh_freeqhull( False);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+#endif
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/qdelaun.c b/extern/qhull/src/qdelaun.c
new file mode 100644
index 00000000000..0e49d9c381e
--- /dev/null
+++ b/extern/qhull/src/qdelaun.c
@@ -0,0 +1,323 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qdelaun.c
+ compute Delaunay triangulations and furthest-point Delaunay
+ triangulations using qhull
+
+ see unix.c for full interface
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+
+#elif __cplusplus
+extern "C" {
+ int isatty (int);
+}
+
+#elif _MSC_VER
+#include <io.h>
+#define isatty _isatty
+
+#else
+int isatty (int); /* returns 1 if stdin is a tty
+ if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt">-</a>
+
+ qh_prompt
+ long prompt for qhull
+
+ notes:
+ restricted version of qhull.c
+
+ see:
+ concise prompt below
+*/
+
+/* duplicated in qdelau_f.htm and qdelaun.htm */
+char hidden_options[]=" d n v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V FC Fi Fo Ft Fp FV Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qdelaunay- compute the Delaunay triangulation\n\
+ http://www.geom.umn.edu/software/qhull %s\n\
+\n\
+input (stdin):\n\
+ first lines: dimension and number of points (or vice-versa).\n\
+ other lines: point coordinates, best if one point per line\n\
+ comments: start with a non-numeric character\n\
+\n\
+options:\n\
+ Qu - compute furthest-site Delaunay triangulation\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+\n\
+Qhull control options:\n\
+ QJn - randomly joggle input in range [-n,n]\n\
+%s%s%s%s"; /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+ Qs - search all points for the initial simplex\n\
+ Qz - add point-at-infinity to Delaunay triangulation\n\
+ QGn - print Delaunay region if visible from point n, -n if not\n\
+ QVn - print Delaunay regions that include point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+ T4 - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+ Tc - check frequently during execution\n\
+ Ts - print statistics\n\
+ Tv - verify result: structure, convexity, and in-circle test\n\
+ Tz - send all output to stdout\n\
+ TFn - report summary when n or more facets created\n\
+ TI file - input data from file, no spaces or single quotes\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+ TPn - turn on tracing when point n added to hull\n\
+ TMn - turn on tracing at merge n\n\
+ TWn - trace merge facets when width > n\n\
+ TVn - stop qhull after adding point n, -n for before (see TCn)\n\
+ TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+ Cn - radius of centrum (roundoff added). Merge facets if non-convex\n\
+ An - cosine of maximum angle. Merge facets if cosine > n or non-convex\n\
+ C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+ Rn - randomly perturb computations by a factor of [1-n,1+n]\n\
+ Wn - min facet width for outside point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+ f - facet dump\n\
+ G - Geomview output (see below)\n\
+ i - vertices incident to each Delaunay region\n\
+ m - Mathematica output (2-d only, lifted to a paraboloid)\n\
+ o - OFF format (dim, points, and facets as a paraboloid)\n\
+ p - point coordinates (lifted to a paraboloid)\n\
+ s - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+ Fa - area for each Delaunay region\n\
+ FA - compute total area for option 's'\n\
+ Fc - count plus coincident points for each Delaunay region\n\
+ Fd - use cdd format for input (homogeneous with offset first)\n\
+ FD - use cdd format for numeric output (offset first)\n\
+ FF - facet dump without ridges\n\
+ FI - ID of each Delaunay region\n\
+ Fm - merge count for each Delaunay region (511 max)\n\
+ Fn - count plus neighboring region for each Delaunay region\n\
+ FN - count plus neighboring region for each point\n\
+ FO - options and precision constants\n\
+ FP - nearest point and distance for each coincident point\n\
+ FQ - command used for qdelaunay\n\
+ Fs - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+ for output: #vertices, #Delaunay regions,\n\
+ #coincident points, #non-simplicial regions\n\
+ #real (2), max outer plane, min vertex\n\
+ FS - sizes: #int (0)\n\
+ #real(2) tot area, 0\n\
+ Fv - count plus vertices for each Delaunay region\n\
+ Fx - extreme points of Delaunay triangulation (on convex hull)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d and 3-d)\n\
+ Ga - all points as dots\n\
+ Gp - coplanar points and vertices as radii\n\
+ Gv - vertices as spheres\n\
+ Gi - inner planes only\n\
+ Gn - no planes\n\
+ Go - outer planes only\n\
+ Gc - centrums\n\
+ Gh - hyperplane intersections\n\
+ Gr - ridges\n\
+ GDn - drop dimension n in 3-d and 4-d output\n\
+ Gt - transparent outer ridges to view 3-d Delaunay\n\
+\n\
+Print options:\n\
+ PAn - keep n largest Delaunay regions by area\n\
+ Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+ PDk:n - drop facet if normal[k] >= n\n\
+ Pg - print good Delaunay regions (needs 'QGn' or 'QVn')\n\
+ PFn - keep Delaunay regions whose area is at least n\n\
+ PG - print neighbors of good regions (needs 'QGn' or 'QVn')\n\
+ PMn - keep n Delaunay regions with most merges\n\
+ Po - force output. If error, output neighborhood of facet\n\
+ Pp - do not report precision problems\n\
+\n\
+ . - list of all options\n\
+ - - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt2">-</a>
+
+ qh_prompt2
+ synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qdelaunay- compute the Delaunay triangulation. Qhull %s\n\
+ input (stdin): dimension, number of points, point coordinates\n\
+ comments start with a non-numeric character\n\
+\n\
+options (qdelaun.htm):\n\
+ Qu - furthest-site Delaunay triangulation\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Tv - verify result: structure, convexity, and in-circle test\n\
+ . - concise list of all options\n\
+ - - one-line description of all options\n\
+\n\
+output options (subset):\n\
+ s - summary of results (default)\n\
+ i - vertices incident to each Delaunay region\n\
+ Fx - extreme points (vertices of the convex hull)\n\
+ o - OFF format (shows the points lifted to a paraboloid)\n\
+ G - Geomview output (2-d and 3-d points lifted to a paraboloid)\n\
+ m - Mathematica output (2-d inputs lifted to a paraboloid)\n\
+ QVn - print Delaunay regions that include point n, -n if not\n\
+ TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+ rbox c P0 D2 | qdelaunay s o rbox c P0 D2 | qdelaunay i\n\
+ rbox c P0 D2 | qdelaunay Fv rbox c P0 D2 | qdelaunay s Qu Fv\n\
+ rbox c G1 d D2 | qdelaunay s i rbox c G1 d D2 | qdelaunay Qt\n\
+ rbox M3,4 z 100 D2 | qdelaunay s rbox M3,4 z 100 D2 | qdelaunay s Qt\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt3">-</a>
+
+ qh_prompt3
+ concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ incidences mathematica OFF_format points_lifted summary\n\
+ facet_dump\n\
+\n\
+ Farea FArea_total Fcoincident Fd_cdd_in FD_cdd_out\n\
+ FF_dump_xridge FIDs Fmerges Fneighbors FNeigh_vertex\n\
+ FOptions FPoint_near FQdelaun Fsummary FSize\n\
+ Fvertices Fxtremes\n\
+\n\
+ Gvertices Gpoints Gall_points Gno_planes Ginner\n\
+ Gcentrums Ghyperplanes Gridges Gouter GDrop_dim\n\
+ Gtransparent\n\
+\n\
+ PArea_keep Pdrop d0:0D0 Pgood PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep Poutput_forced Pprecision_not\n\
+\n\
+ QGood_point QJoggle Qsearch_1st Qtriangulate QupperDelaunay\n\
+ QVertex_good Qzinfinite\n\
+\n\
+ T4_trace Tcheck_often Tstatistics Tverify Tz_stdout\n\
+ TFacet_log TInput_file TPoint_trace TMerge_trace TOutput_file\n\
+ TWide_trace TVertex_stop TCone_stop\n\
+\n\
+ Angle_max Centrum_size Random_dist Wide_outside\n\
+";
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="main">-</a>
+
+ main( argc, argv )
+ processes the command line, calls qhull() to do the work, and exits
+
+ design:
+ initializes data structures
+ reads points
+ finishes initialization
+ computes convex hull and other structures
+ checks the result
+ writes the output
+ frees memory
+*/
+int main(int argc, char *argv[]) {
+ int curlong, totlong; /* used !qh_NOmem */
+ int exitcode, numpoints, dim;
+ coordT *points;
+ boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= false;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+
+ if ((argc == 1) && isatty( 0 /*stdin*/)) {
+ fprintf(stdout, qh_prompt2, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompta, qh_VERSION,
+ qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+ exit(qh_ERRnone);
+ }
+ if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompt3, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ qh_init_A (stdin, stdout, stderr, argc, argv); /* sets qh qhull_command */
+ exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+ if (!exitcode) {
+ qh_option ("delaunay Qbbound-last", NULL, NULL);
+ qh DELAUNAY= True; /* 'd' */
+ qh SCALElast= True; /* 'Qbb' */
+ qh KEEPcoplanar= True; /* 'Qc', to keep coplanars in 'p' */
+ qh_checkflags (qh qhull_command, hidden_options);
+ qh_initflags (qh qhull_command);
+ points= qh_readpoints (&numpoints, &dim, &ismalloc);
+ if (dim >= 5) {
+ qh_option ("Qxact_merge", NULL, NULL);
+ qh MERGEexact= True; /* 'Qx' always */
+ }
+ qh_init_B (points, numpoints, dim, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ exitcode= qh_ERRnone;
+ }
+ qh NOerrexit= True; /* no more setjmp */
+#ifdef qh_NOmem
+ qh_freeqhull( True);
+#else
+ qh_freeqhull( False);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+#endif
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/qhalf.c b/extern/qhull/src/qhalf.c
new file mode 100644
index 00000000000..a2b3875dd7f
--- /dev/null
+++ b/extern/qhull/src/qhalf.c
@@ -0,0 +1,324 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhalf.c
+ compute the intersection of halfspaces about a point
+
+ see unix.c for full interface
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+
+#elif __cplusplus
+extern "C" {
+ int isatty (int);
+}
+
+#elif _MSC_VER
+#include <io.h>
+#define isatty _isatty
+
+#else
+int isatty (int); /* returns 1 if stdin is a tty
+ if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt">-</a>
+
+ qh_prompt
+ long prompt for qhull
+
+ notes:
+ restricted version of qhull.c
+
+ see:
+ concise prompt below
+*/
+
+/* duplicated in qhalf.htm */
+char hidden_options[]=" d n v Qbb QbB Qf Qg Qm Qr QR Qv Qx Qz TR E V Fa FA FC FD FS Ft FV Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qhalf- compute the intersection of halfspaces about a point\n\
+ http://www.geom.umn.edu/software/qhull %s\n\
+\n\
+input (stdin):\n\
+ optional interior point: dimension, 1, coordinates\n\
+ first lines: dimension+1 and number of halfspaces\n\
+ other lines: halfspace coefficients followed by offset\n\
+ comments: start with a non-numeric character\n\
+\n\
+options:\n\
+ Hn,n - specify coordinates of interior point\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Qc - keep coplanar halfspaces\n\
+ Qi - keep other redundant halfspaces\n\
+\n\
+Qhull control options:\n\
+ QJn - randomly joggle input in range [-n,n]\n\
+%s%s%s%s"; /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+ Qbk:0Bk:0 - remove k-th coordinate from input\n\
+ Qs - search all halfspaces for the initial simplex\n\
+ QGn - print intersection if visible to halfspace n, -n for not\n\
+ QVn - print intersections for halfspace n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+ T4 - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+ Tc - check frequently during execution\n\
+ Ts - print statistics\n\
+ Tv - verify result: structure, convexity, and redundancy\n\
+ Tz - send all output to stdout\n\
+ TFn - report summary when n or more facets created\n\
+ TI file - input data from file, no spaces or single quotes\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+ TPn - turn on tracing when halfspace n added to intersection\n\
+ TMn - turn on tracing at merge n\n\
+ TWn - trace merge facets when width > n\n\
+ TVn - stop qhull after adding halfspace n, -n for before (see TCn)\n\
+ TCn - stop qhull after building cone for halfspace n (see TVn)\n\
+\n\
+Precision options:\n\
+ Cn - radius of centrum (roundoff added). Merge facets if non-convex\n\
+ An - cosine of maximum angle. Merge facets if cosine > n or non-convex\n\
+ C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+ Rn - randomly perturb computations by a factor of [1-n,1+n]\n\
+ Un - max distance below plane for a new, coplanar halfspace\n\
+ Wn - min facet width for outside halfspace (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+ f - facet dump\n\
+ G - Geomview output (dual convex hull)\n\
+ i - non-redundant halfspaces incident to each intersection\n\
+ m - Mathematica output (dual convex hull)\n\
+ o - OFF format (dual convex hull: dimension, points, and facets)\n\
+ p - vertex coordinates of dual convex hull (coplanars if 'Qc' or 'Qi')\n\
+ s - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+ Fc - count plus redundant halfspaces for each intersection\n\
+ - Qc (default) for coplanar and Qi for other redundant\n\
+ Fd - use cdd format for input (homogeneous with offset first)\n\
+ FF - facet dump without ridges\n\
+ FI - ID of each intersection\n\
+ Fm - merge count for each intersection (511 max)\n\
+ Fn - count plus neighboring intersections for each intersection\n\
+ FN - count plus intersections for each non-redundant halfspace\n\
+ FO - options and precision constants\n\
+ Fp - dim, count, and intersection coordinates\n\
+ FP - nearest halfspace and distance for each redundant halfspace\n\
+ FQ - command used for qhalf\n\
+ Fs - summary: #int (8), dim, #halfspaces, #non-redundant, #intersections\n\
+ for output: #non-redundant, #intersections, #coplanar\n\
+ halfspaces, #non-simplicial intersections\n\
+ #real (2), max outer plane, min vertex\n\
+ Fv - count plus non-redundant halfspaces for each intersection\n\
+ Fx - non-redundant halfspaces\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview output (2-d, 3-d and 4-d; dual convex hull)\n\
+ Ga - all points (i.e., transformed halfspaces) as dots\n\
+ Gp - coplanar points and vertices as radii\n\
+ Gv - vertices (i.e., non-redundant halfspaces) as spheres\n\
+ Gi - inner planes (i.e., halfspace intersections) only\n\
+ Gn - no planes\n\
+ Go - outer planes only\n\
+ Gc - centrums\n\
+ Gh - hyperplane intersections\n\
+ Gr - ridges\n\
+ GDn - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+ PAn - keep n largest facets (i.e., intersections) by area\n\
+ Pdk:n- drop facet if normal[k] <= n (default 0.0)\n\
+ PDk:n- drop facet if normal[k] >= n\n\
+ Pg - print good facets (needs 'QGn' or 'QVn')\n\
+ PFn - keep facets whose area is at least n\n\
+ PG - print neighbors of good facets\n\
+ PMn - keep n facets with most merges\n\
+ Po - force output. If error, output neighborhood of facet\n\
+ Pp - do not report precision problems\n\
+\n\
+ . - list of all options\n\
+ - - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt2">-</a>
+
+ qh_prompt2
+ synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qhalf- halfspace intersection about a point. Qhull %s\n\
+ input (stdin): [dim, 1, interior point], dim+1, n, coefficients+offset\n\
+ comments start with a non-numeric character\n\
+\n\
+options (qhalf.htm):\n\
+ Hn,n - specify coordinates of interior point\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Tv - verify result: structure, convexity, and redundancy\n\
+ . - concise list of all options\n\
+ - - one-line description of all options\n\
+\n\
+output options (subset):\n\
+ s - summary of results (default)\n\
+ Fp - intersection coordinates\n\
+ Fv - non-redundant halfspaces incident to each intersection\n\
+ Fx - non-redundant halfspaces\n\
+ o - OFF file format (dual convex hull)\n\
+ G - Geomview output (dual convex hull)\n\
+ m - Mathematica output (dual convex hull)\n\
+ QVn - print intersections for halfspace n, -n if not\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+ rbox d | qconvex FQ n | qhalf s H0,0,0 Fp\n\
+ rbox c | qconvex FQ FV n | qhalf s i\n\
+ rbox c | qconvex FQ FV n | qhalf s o\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt3">-</a>
+
+ qh_prompt3
+ concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper_case options take an argument.\n\
+\n\
+ incidences Geomview mathematica OFF_format point_dual\n\
+ summary facet_dump\n\
+\n\
+ Fc_redundant Fd_cdd_in FF_dump_xridge FIDs Fmerges\n\
+ Fneighbors FN_intersect FOptions Fp_coordinates FP_nearest\n\
+ FQhalf Fsummary Fv_halfspace Fx_non_redundant\n\
+\n\
+ Gvertices Gpoints Gall_points Gno_planes Ginner\n\
+ Gcentrums Ghyperplanes Gridges Gouter GDrop_dim\n\
+\n\
+ PArea_keep Pdrop d0:0D0 Pgood PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep Poutput_forced Pprecision_not\n\
+\n\
+ Qbk:0Bk:0_drop Qcoplanar QG_half_good Qi_redundant QJoggle\n\
+ Qsearch_1st Qtriangulate QVertex_good\n\
+\n\
+ T4_trace Tcheck_often Tstatistics Tverify Tz_stdout\n\
+ TFacet_log TInput_file TPoint_trace TMerge_trace TOutput_file\n\
+ TWide_trace TVertex_stop TCone_stop\n\
+\n\
+ Angle_max Centrum_size Random_dist Ucoplanar_max Wide_outside\n\
+";
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="main">-</a>
+
+ main( argc, argv )
+ processes the command line, calls qhull() to do the work, and exits
+
+ design:
+ initializes data structures
+ reads points
+ finishes initialization
+ computes convex hull and other structures
+ checks the result
+ writes the output
+ frees memory
+*/
+int main(int argc, char *argv[]) {
+ int curlong, totlong; /* used !qh_NOmem */
+ int exitcode, numpoints, dim;
+ coordT *points;
+ boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= false;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+
+ if ((argc == 1) && isatty( 0 /*stdin*/)) {
+ fprintf(stdout, qh_prompt2, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompta, qh_VERSION,
+ qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+ exit(qh_ERRnone);
+ }
+ if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompt3, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ qh_init_A (stdin, stdout, stderr, argc, argv); /* sets qh qhull_command */
+ exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+ if (!exitcode) {
+ qh_option ("Halfspace", NULL, NULL);
+ qh HALFspace= True; /* 'H' */
+ qh_checkflags (qh qhull_command, hidden_options);
+ qh_initflags (qh qhull_command);
+ if (qh SCALEinput) {
+ fprintf(qh ferr, "\
+qhull error: options 'Qbk:n' and 'QBk:n' are not used with qhalf.\n\
+ Use 'Qbk:0Bk:0 to drop dimension k.\n");
+ qh_errexit(qh_ERRinput, NULL, NULL);
+ }
+ points= qh_readpoints (&numpoints, &dim, &ismalloc);
+ if (dim >= 5) {
+ qh_option ("Qxact_merge", NULL, NULL);
+ qh MERGEexact= True; /* 'Qx' always */
+ }
+ qh_init_B (points, numpoints, dim, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ exitcode= qh_ERRnone;
+ }
+ qh NOerrexit= True; /* no more setjmp */
+#ifdef qh_NOmem
+ qh_freeqhull( True);
+#else
+ qh_freeqhull( False);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+#endif
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/qhull.c b/extern/qhull/src/qhull.c
new file mode 100644
index 00000000000..dc835bb4f28
--- /dev/null
+++ b/extern/qhull/src/qhull.c
@@ -0,0 +1,1395 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhull.c
+ Quickhull algorithm for convex hulls
+
+ qhull() and top-level routines
+
+ see qh-qhull.htm, qhull.h, unix.c
+
+ see qhull_a.h for internal functions
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*============= functions in alphabetic order after qhull() =======*/
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="qhull">-</a>
+
+ qh_qhull()
+ compute DIM3 convex hull of qh.num_points starting at qh.first_point
+ qh contains all global options and variables
+
+ returns:
+ returns polyhedron
+ qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
+
+ returns global variables
+ qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
+
+ returns precision constants
+ qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
+
+ notes:
+ unless needed for output
+ qh.max_vertex and qh.min_vertex are max/min due to merges
+
+ see:
+ to add individual points to either qh.num_points
+ use qh_addpoint()
+
+ if qh.GETarea
+ qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
+
+ design:
+ record starting time
+ initialize hull and partition points
+ build convex hull
+ unless early termination
+ update facet->maxoutside for vertices, coplanar, and near-inside points
+ error if temporary sets exist
+ record end time
+*/
+void qh_qhull (void) {
+ int numoutside;
+
+ qh hulltime= qh_CPUclock;
+ if (qh RERUN || qh JOGGLEmax < REALmax/2)
+ qh_build_withrestart();
+ else {
+ qh_initbuild();
+ qh_buildhull();
+ }
+ if (!qh STOPpoint && !qh STOPcone) {
+ if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
+ qh_checkzero( qh_ALL);
+ if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
+ trace2((qh ferr, "qh_qhull: all facets are clearly convex and no coplanar points. Post-merging and check of maxout not needed.\n"));
+ qh DOcheckmax= False;
+ }else {
+ if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
+ qh_postmerge ("First post-merge", qh premerge_centrum, qh premerge_cos,
+ (qh POSTmerge ? False : qh TESTvneighbors));
+ else if (!qh POSTmerge && qh TESTvneighbors)
+ qh_postmerge ("For testing vertex neighbors", qh premerge_centrum,
+ qh premerge_cos, True);
+ if (qh POSTmerge)
+ qh_postmerge ("For post-merging", qh postmerge_centrum,
+ qh postmerge_cos, qh TESTvneighbors);
+ if (qh visible_list == qh facet_list) { /* i.e., merging done */
+ qh findbestnew= True;
+ qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numoutside);
+ qh findbestnew= False;
+ qh_deletevisible (/*qh visible_list*/);
+ qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+ }
+ }
+ if (qh DOcheckmax){
+ if (qh REPORTfreq) {
+ qh_buildtracing (NULL, NULL);
+ fprintf (qh ferr, "\nTesting all coplanar points.\n");
+ }
+ qh_check_maxout();
+ }
+ if (qh KEEPnearinside && !qh maxoutdone)
+ qh_nearcoplanar();
+ }
+ if (qh_setsize ((setT*)qhmem.tempstack) != 0) {
+ fprintf (qh ferr, "qhull internal error (qh_qhull): temporary sets not empty (%d)\n",
+ qh_setsize ((setT*)qhmem.tempstack));
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ qh hulltime= qh_CPUclock - qh hulltime;
+ qh QHULLfinished= True;
+ trace1((qh ferr, "qh_qhull: algorithm completed\n"));
+} /* qhull */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="addpoint">-</a>
+
+ qh_addpoint( furthest, facet, checkdist )
+ add point (usually furthest point) above facet to hull
+ if checkdist,
+ check that point is above facet.
+ if point is not outside of the hull, uses qh_partitioncoplanar()
+ assumes that facet is defined by qh_findbestfacet()
+ else if facet specified,
+ assumes that point is above facet (major damage if below)
+ for Delaunay triangulations,
+ Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+ Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+ returns:
+ returns False if user requested an early termination
+ qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
+ updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+ clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
+ if unknown point, adds a pointer to qh.other_points
+ do not deallocate the point's coordinates
+
+ notes:
+ assumes point is near its best facet and not at a local minimum of a lens
+ distributions. Use qh_findbestfacet to avoid this case.
+ uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
+
+ see also:
+ qh_triangulate() -- triangulate non-simplicial facets
+
+ design:
+ check point in qh.first_point/.num_points
+ if checkdist
+ if point not above facet
+ partition coplanar point
+ exit
+ exit if pre STOPpoint requested
+ find horizon and visible facets for point
+ make new facets for point to horizon
+ make hyperplanes for point
+ compute balance statistics
+ match neighboring new facets
+ update vertex neighbors and delete interior vertices
+ exit if STOPcone requested
+ merge non-convex new facets
+ if merge found, many merges, or 'Qf'
+ use qh_findbestnew() instead of qh_findbest()
+ partition outside points from visible facets
+ delete visible facets
+ check polyhedron if requested
+ exit if post STOPpoint requested
+ reset working lists of facets and vertices
+*/
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist) {
+ int goodvisible, goodhorizon;
+ vertexT *vertex;
+ facetT *newfacet;
+ realT dist, newbalance, pbalance;
+ boolT isoutside= False;
+ int numpart, numpoints, numnew, firstnew;
+
+ qh maxoutdone= False;
+ if (qh_pointid (furthest) == -1)
+ qh_setappend (&qh other_points, furthest);
+ if (!facet) {
+ fprintf (qh ferr, "qh_addpoint: NULL facet. Need to call qh_findbestfacet first\n");
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ if (checkdist) {
+ facet= qh_findbest (furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
+ &dist, &isoutside, &numpart);
+ zzadd_(Zpartition, numpart);
+ if (!isoutside) {
+ zinc_(Znotmax); /* last point of outsideset is no longer furthest. */
+ facet->notfurthest= True;
+ qh_partitioncoplanar (furthest, facet, &dist);
+ return True;
+ }
+ }
+ qh_buildtracing (furthest, facet);
+ if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
+ facet->notfurthest= True;
+ return False;
+ }
+ qh_findhorizon (furthest, facet, &goodvisible, &goodhorizon);
+ if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
+ zinc_(Znotgood);
+ facet->notfurthest= True;
+ /* last point of outsideset is no longer furthest. This is ok
+ since all points of the outside are likely to be bad */
+ qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+ return True;
+ }
+ zzinc_(Zprocessed);
+ firstnew= qh facet_id;
+ vertex= qh_makenewfacets (furthest /*visible_list, attaches if !ONLYgood */);
+ qh_makenewplanes (/* newfacet_list */);
+ numnew= qh facet_id - firstnew;
+ newbalance= numnew - (realT) (qh num_facets-qh num_visible)
+ * qh hull_dim/qh num_vertices;
+ wadd_(Wnewbalance, newbalance);
+ wadd_(Wnewbalance2, newbalance * newbalance);
+ if (qh ONLYgood
+ && !qh_findgood (qh newfacet_list, goodhorizon) && !qh GOODclosest) {
+ FORALLnew_facets
+ qh_delfacet (newfacet);
+ qh_delvertex (vertex);
+ qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+ zinc_(Znotgoodnew);
+ facet->notfurthest= True;
+ return True;
+ }
+ if (qh ONLYgood)
+ qh_attachnewfacets(/*visible_list*/);
+ qh_matchnewfacets();
+ qh_updatevertices();
+ if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
+ facet->notfurthest= True;
+ return False; /* visible_list etc. still defined */
+ }
+ qh findbestnew= False;
+ if (qh PREmerge || qh MERGEexact) {
+ qh_premerge (vertex, qh premerge_centrum, qh premerge_cos);
+ if (qh_USEfindbestnew)
+ qh findbestnew= True;
+ else {
+ FORALLnew_facets {
+ if (!newfacet->simplicial) {
+ qh findbestnew= True; /* use qh_findbestnew instead of qh_findbest*/
+ break;
+ }
+ }
+ }
+ }else if (qh BESToutside)
+ qh findbestnew= True;
+ qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numpoints);
+ qh findbestnew= False;
+ qh findbest_notsharp= False;
+ zinc_(Zpbalance);
+ pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
+ * (qh num_points - qh num_vertices)/qh num_vertices;
+ wadd_(Wpbalance, pbalance);
+ wadd_(Wpbalance2, pbalance * pbalance);
+ qh_deletevisible (/*qh visible_list*/);
+ zmax_(Zmaxvertex, qh num_vertices);
+ qh NEWfacets= False;
+ if (qh IStracing >= 4) {
+ if (qh num_facets < 2000)
+ qh_printlists();
+ qh_printfacetlist (qh newfacet_list, NULL, True);
+ qh_checkpolygon (qh facet_list);
+ }else if (qh CHECKfrequently) {
+ if (qh num_facets < 50)
+ qh_checkpolygon (qh facet_list);
+ else
+ qh_checkpolygon (qh newfacet_list);
+ }
+ if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1)
+ return False;
+ qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+ /* qh_triangulate(); to test qh.TRInormals */
+ trace2((qh ferr, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
+ qh_pointid (furthest), numnew, newbalance, pbalance));
+ return True;
+} /* addpoint */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="build_withrestart">-</a>
+
+ qh_build_withrestart()
+ allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
+ qh.FIRSTpoint/qh.NUMpoints is point array
+ it may be moved by qh_joggleinput()
+*/
+void qh_build_withrestart (void) {
+ int restart;
+
+ qh ALLOWrestart= True;
+ while (True) {
+ restart= setjmp (qh restartexit); /* simple statement for CRAY J916 */
+ if (restart) { /* only from qh_precision() */
+ zzinc_(Zretry);
+ wmax_(Wretrymax, qh JOGGLEmax);
+ qh ERREXITcalled= False;
+ qh STOPcone= True; /* if break, prevents normal output */
+ }
+ if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
+ if (qh build_cnt > qh_JOGGLEmaxretry) {
+ fprintf(qh ferr, "\n\
+qhull precision error: %d attempts to construct a convex hull\n\
+ with joggled input. Increase joggle above 'QJ%2.2g'\n\
+ or modify qh_JOGGLE... parameters in user.h\n",
+ qh build_cnt, qh JOGGLEmax);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ if (qh build_cnt && !restart)
+ break;
+ }else if (qh build_cnt && qh build_cnt >= qh RERUN)
+ break;
+ qh STOPcone= False;
+ qh_freebuild (True); /* first call is a nop */
+ qh build_cnt++;
+ if (!qh qhull_optionsiz)
+ qh qhull_optionsiz= strlen (qh qhull_options);
+ else {
+ qh qhull_options [qh qhull_optionsiz]= '\0';
+ qh qhull_optionlen= 80;
+ }
+ qh_option("_run", &qh build_cnt, NULL);
+ if (qh build_cnt == qh RERUN) {
+ qh IStracing= qh TRACElastrun; /* duplicated from qh_initqhull_globals */
+ if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+ qh TRACElevel= (qh IStracing? qh IStracing : 3);
+ qh IStracing= 0;
+ }
+ qhmem.IStracing= qh IStracing;
+ }
+ if (qh JOGGLEmax < REALmax/2)
+ qh_joggleinput();
+ qh_initbuild();
+ qh_buildhull();
+ if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
+ qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+ }
+ qh ALLOWrestart= False;
+} /* qh_build_withrestart */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="buildhull">-</a>
+
+ qh_buildhull()
+ construct a convex hull by adding outside points one at a time
+
+ returns:
+
+ notes:
+ may be called multiple times
+ checks facet and vertex lists for incorrect flags
+ to recover from STOPcone, call qh_deletevisible and qh_resetlists
+
+ design:
+ check visible facet and newfacet flags
+ check newlist vertex flags and qh.STOPcone/STOPpoint
+ for each facet with a furthest outside point
+ add point to facet
+ exit if qh.STOPcone or qh.STOPpoint requested
+ if qh.NARROWhull for initial simplex
+ partition remaining outside points to coplanar sets
+*/
+void qh_buildhull(void) {
+ facetT *facet;
+ pointT *furthest;
+ vertexT *vertex;
+ int id;
+
+ trace1((qh ferr, "qh_buildhull: start build hull\n"));
+ FORALLfacets {
+ if (facet->visible || facet->newfacet) {
+ fprintf (qh ferr, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
+ facet->id);
+ qh_errexit (qh_ERRqhull, facet, NULL);
+ }
+ }
+ FORALLvertices {
+ if (vertex->newlist) {
+ fprintf (qh ferr, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
+ vertex->id);
+ qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ id= qh_pointid (vertex->point);
+ if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
+ (qh STOPpoint<0 && id == -qh STOPpoint-1) ||
+ (qh STOPcone>0 && id == qh STOPcone-1)) {
+ trace1((qh ferr,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
+ return;
+ }
+ }
+ qh facet_next= qh facet_list; /* advance facet when processed */
+ while ((furthest= qh_nextfurthest (&facet))) {
+ qh num_outside--; /* if ONLYmax, furthest may not be outside */
+ if (!qh_addpoint (furthest, facet, qh ONLYmax))
+ break;
+ }
+ if (qh NARROWhull) /* move points from outsideset to coplanarset */
+ qh_outcoplanar( /* facet_list */ );
+ if (qh num_outside && !furthest) {
+ fprintf (qh ferr, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }
+ trace1((qh ferr, "qh_buildhull: completed the hull construction\n"));
+} /* buildhull */
+
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="buildtracing">-</a>
+
+ qh_buildtracing( furthest, facet )
+ trace an iteration of qh_buildhull() for furthest point and facet
+ if !furthest, prints progress message
+
+ returns:
+ tracks progress with qh.lastreport
+ updates qh.furthest_id (-3 if furthest is NULL)
+ also resets visit_id, vertext_visit on wrap around
+
+ see:
+ qh_tracemerging()
+
+ design:
+ if !furthest
+ print progress message
+ exit
+ if 'TFn' iteration
+ print progress message
+ else if tracing
+ trace furthest point and facet
+ reset qh.visit_id and qh.vertex_visit if overflow may occur
+ set qh.furthest_id for tracing
+*/
+void qh_buildtracing (pointT *furthest, facetT *facet) {
+ realT dist= 0;
+ float cpu;
+ int total, furthestid;
+ time_t timedata;
+ struct tm *tp;
+ vertexT *vertex;
+
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ if (!furthest) {
+ time (&timedata);
+ tp= localtime (&timedata);
+ cpu= qh_CPUclock - qh hulltime;
+ cpu /= qh_SECticks;
+ total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+ fprintf (qh ferr, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices. Last point was p%d\n",
+ tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+ total, qh num_facets, qh num_vertices, qh furthest_id);
+ return;
+ }
+ furthestid= qh_pointid (furthest);
+ if (qh TRACEpoint == furthestid) {
+ qh IStracing= qh TRACElevel;
+ qhmem.IStracing= qh TRACElevel;
+ }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) {
+ qh IStracing= 0;
+ qhmem.IStracing= 0;
+ }
+ if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
+ qh lastreport= qh facet_id-1;
+ time (&timedata);
+ tp= localtime (&timedata);
+ cpu= qh_CPUclock - qh hulltime;
+ cpu /= qh_SECticks;
+ total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+ zinc_(Zdistio);
+ qh_distplane (furthest, facet, &dist);
+ fprintf (qh ferr, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices. There are %d\n\
+ outside points. Next is point p%d (v%d), %2.2g above f%d.\n",
+ tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+ total, qh num_facets, qh num_vertices, qh num_outside+1,
+ furthestid, qh vertex_id, dist, getid_(facet));
+ }else if (qh IStracing >=1) {
+ cpu= qh_CPUclock - qh hulltime;
+ cpu /= qh_SECticks;
+ qh_distplane (furthest, facet, &dist);
+ fprintf (qh ferr, "qh_addpoint: add p%d (v%d) to hull of %d facets (%2.2g above f%d) and %d outside at %4.4g CPU secs. Previous was p%d.\n",
+ furthestid, qh vertex_id, qh num_facets, dist,
+ getid_(facet), qh num_outside+1, cpu, qh furthest_id);
+ }
+ if (qh visit_id > (unsigned) INT_MAX) {
+ qh visit_id= 0;
+ FORALLfacets
+ facet->visitid= qh visit_id;
+ }
+ if (qh vertex_visit > (unsigned) INT_MAX) {
+ qh vertex_visit= 0;
+ FORALLvertices
+ vertex->visitid= qh vertex_visit;
+ }
+ qh furthest_id= furthestid;
+ qh RANDOMdist= qh old_randomdist;
+} /* buildtracing */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="errexit2">-</a>
+
+ qh_errexit2( exitcode, facet, otherfacet )
+ return exitcode to system after an error
+ report two facets
+
+ returns:
+ assumes exitcode non-zero
+
+ see:
+ normally use qh_errexit() in user.c (reports a facet and a ridge)
+*/
+void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
+
+ qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
+ qh_errexit (exitcode, NULL, NULL);
+} /* errexit2 */
+
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="findhorizon">-</a>
+
+ qh_findhorizon( point, facet, goodvisible, goodhorizon )
+ given a visible facet, find the point's horizon and visible facets
+ for all facets, !facet-visible
+
+ returns:
+ returns qh.visible_list/num_visible with all visible facets
+ marks visible facets with ->visible
+ updates count of good visible and good horizon facets
+ updates qh.max_outside, qh.max_vertex, facet->maxoutside
+
+ see:
+ similar to qh_delpoint()
+
+ design:
+ move facet to qh.visible_list at end of qh.facet_list
+ for all visible facets
+ for each unvisited neighbor of a visible facet
+ compute distance of point to neighbor
+ if point above neighbor
+ move neighbor to end of qh.visible_list
+ else if point is coplanar with neighbor
+ update qh.max_outside, qh.max_vertex, neighbor->maxoutside
+ mark neighbor coplanar (will create a samecycle later)
+ update horizon statistics
+*/
+void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
+ facetT *neighbor, **neighborp, *visible;
+ int numhorizon= 0, coplanar= 0;
+ realT dist;
+
+ trace1((qh ferr,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
+ *goodvisible= *goodhorizon= 0;
+ zinc_(Ztotvisible);
+ qh_removefacet(facet); /* visible_list at end of qh facet_list */
+ qh_appendfacet(facet);
+ qh num_visible= 1;
+ if (facet->good)
+ (*goodvisible)++;
+ qh visible_list= facet;
+ facet->visible= True;
+ facet->f.replace= NULL;
+ if (qh IStracing >=4)
+ qh_errprint ("visible", facet, NULL, NULL, NULL);
+ qh visit_id++;
+ FORALLvisible_facets {
+ if (visible->tricoplanar && !qh TRInormals) {
+ fprintf (qh ferr, "qh_findhorizon: does not work for tricoplanar facets. Use option 'Q11'\n");
+ qh_errexit (qh_ERRqhull, visible, NULL);
+ }
+ visible->visitid= qh visit_id;
+ FOREACHneighbor_(visible) {
+ if (neighbor->visitid == qh visit_id)
+ continue;
+ neighbor->visitid= qh visit_id;
+ zzinc_(Znumvisibility);
+ qh_distplane(point, neighbor, &dist);
+ if (dist > qh MINvisible) {
+ zinc_(Ztotvisible);
+ qh_removefacet(neighbor); /* append to end of qh visible_list */
+ qh_appendfacet(neighbor);
+ neighbor->visible= True;
+ neighbor->f.replace= NULL;
+ qh num_visible++;
+ if (neighbor->good)
+ (*goodvisible)++;
+ if (qh IStracing >=4)
+ qh_errprint ("visible", neighbor, NULL, NULL, NULL);
+ }else {
+ if (dist > - qh MAXcoplanar) {
+ neighbor->coplanar= True;
+ zzinc_(Zcoplanarhorizon);
+ qh_precision ("coplanar horizon");
+ coplanar++;
+ if (qh MERGING) {
+ if (dist > 0) {
+ maximize_(qh max_outside, dist);
+ maximize_(qh max_vertex, dist);
+#if qh_MAXoutside
+ maximize_(neighbor->maxoutside, dist);
+#endif
+ }else
+ minimize_(qh min_vertex, dist); /* due to merge later */
+ }
+ trace2((qh ferr, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible (%2.7g)\n",
+ qh_pointid(point), neighbor->id, dist, qh MINvisible));
+ }else
+ neighbor->coplanar= False;
+ zinc_(Ztothorizon);
+ numhorizon++;
+ if (neighbor->good)
+ (*goodhorizon)++;
+ if (qh IStracing >=4)
+ qh_errprint ("horizon", neighbor, NULL, NULL, NULL);
+ }
+ }
+ }
+ if (!numhorizon) {
+ qh_precision ("empty horizon");
+ fprintf(qh ferr, "qhull precision error (qh_findhorizon): empty horizon\n\
+Point p%d was above all facets.\n", qh_pointid(point));
+ qh_printfacetlist (qh facet_list, NULL, True);
+ qh_errexit(qh_ERRprec, NULL, NULL);
+ }
+ trace1((qh ferr, "qh_findhorizon: %d horizon facets (good %d), %d visible (good %d), %d coplanar\n",
+ numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
+ if (qh IStracing >= 4 && qh num_facets < 50)
+ qh_printlists ();
+} /* findhorizon */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="nextfurthest">-</a>
+
+ qh_nextfurthest( visible )
+ returns next furthest point and visible facet for qh_addpoint()
+ starts search at qh.facet_next
+
+ returns:
+ removes furthest point from outside set
+ NULL if none available
+ advances qh.facet_next over facets with empty outside sets
+
+ design:
+ for each facet from qh.facet_next
+ if empty outside set
+ advance qh.facet_next
+ else if qh.NARROWhull
+ determine furthest outside point
+ if furthest point is not outside
+ advance qh.facet_next (point will be coplanar)
+ remove furthest point from outside set
+*/
+pointT *qh_nextfurthest (facetT **visible) {
+ facetT *facet;
+ int size, index;
+ realT randr, dist;
+ pointT *furthest;
+
+ while ((facet= qh facet_next) != qh facet_tail) {
+ if (!facet->outsideset) {
+ qh facet_next= facet->next;
+ continue;
+ }
+ SETreturnsize_(facet->outsideset, size);
+ if (!size) {
+ qh_setfree (&facet->outsideset);
+ qh facet_next= facet->next;
+ continue;
+ }
+ if (qh NARROWhull) {
+ if (facet->notfurthest)
+ qh_furthestout (facet);
+ furthest= (pointT*)qh_setlast (facet->outsideset);
+#if qh_COMPUTEfurthest
+ qh_distplane (furthest, facet, &dist);
+ zinc_(Zcomputefurthest);
+#else
+ dist= facet->furthestdist;
+#endif
+ if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
+ qh facet_next= facet->next;
+ continue;
+ }
+ }
+ if (!qh RANDOMoutside && !qh VIRTUALmemory) {
+ if (qh PICKfurthest) {
+ qh_furthestnext (/* qh facet_list */);
+ facet= qh facet_next;
+ }
+ *visible= facet;
+ return ((pointT*)qh_setdellast (facet->outsideset));
+ }
+ if (qh RANDOMoutside) {
+ int outcoplanar = 0;
+ if (qh NARROWhull) {
+ FORALLfacets {
+ if (facet == qh facet_next)
+ break;
+ if (facet->outsideset)
+ outcoplanar += qh_setsize( facet->outsideset);
+ }
+ }
+ randr= qh_RANDOMint;
+ randr= randr/(qh_RANDOMmax+1);
+ index= (int)floor((qh num_outside - outcoplanar) * randr);
+ FORALLfacet_(qh facet_next) {
+ if (facet->outsideset) {
+ SETreturnsize_(facet->outsideset, size);
+ if (!size)
+ qh_setfree (&facet->outsideset);
+ else if (size > index) {
+ *visible= facet;
+ return ((pointT*)qh_setdelnth (facet->outsideset, index));
+ }else
+ index -= size;
+ }
+ }
+ fprintf (qh ferr, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
+ qh num_outside, index+1, randr);
+ qh_errexit (qh_ERRqhull, NULL, NULL);
+ }else { /* VIRTUALmemory */
+ facet= qh facet_tail->previous;
+ if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
+ if (facet->outsideset)
+ qh_setfree (&facet->outsideset);
+ qh_removefacet (facet);
+ qh_prependfacet (facet, &qh facet_list);
+ continue;
+ }
+ *visible= facet;
+ return furthest;
+ }
+ }
+ return NULL;
+} /* nextfurthest */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="partitionall">-</a>
+
+ qh_partitionall( vertices, points, numpoints )
+ partitions all points in points/numpoints to the outsidesets of facets
+ vertices= vertices in qh.facet_list (not partitioned)
+
+ returns:
+ builds facet->outsideset
+ does not partition qh.GOODpoint
+ if qh.ONLYgood && !qh.MERGING,
+ does not partition qh.GOODvertex
+
+ notes:
+ faster if qh.facet_list sorted by anticipated size of outside set
+
+ design:
+ initialize pointset with all points
+ remove vertices from pointset
+ remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
+ for all facets
+ for all remaining points in pointset
+ compute distance from point to facet
+ if point is outside facet
+ remove point from pointset (by not reappending)
+ update bestpoint
+ append point or old bestpoint to facet's outside set
+ append bestpoint to facet's outside set (furthest)
+ for all points remaining in pointset
+ partition point into facets' outside sets and coplanar sets
+*/
+void qh_partitionall(setT *vertices, pointT *points, int numpoints){
+ setT *pointset;
+ vertexT *vertex, **vertexp;
+ pointT *point, **pointp, *bestpoint;
+ int size, point_i, point_n, point_end, remaining, i, id;
+ facetT *facet;
+ realT bestdist= -REALmax, dist, distoutside;
+
+ trace1((qh ferr, "qh_partitionall: partition all points into outside sets\n"));
+ pointset= qh_settemp (numpoints);
+ qh num_outside= 0;
+ pointp= SETaddr_(pointset, pointT);
+ for (i=numpoints, point= points; i--; point += qh hull_dim)
+ *(pointp++)= point;
+ qh_settruncate (pointset, numpoints);
+ FOREACHvertex_(vertices) {
+ if ((id= qh_pointid(vertex->point)) >= 0)
+ SETelem_(pointset, id)= NULL;
+ }
+ id= qh_pointid (qh GOODpointp);
+ if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+ SETelem_(pointset, id)= NULL;
+ if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
+ if ((id= qh_pointid(qh GOODvertexp)) >= 0)
+ SETelem_(pointset, id)= NULL;
+ }
+ if (!qh BESToutside) { /* matches conditional for qh_partitionpoint below */
+ distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+ zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
+ remaining= qh num_facets;
+ point_end= numpoints;
+ FORALLfacets {
+ size= point_end/(remaining--) + 100;
+ facet->outsideset= qh_setnew (size);
+ bestpoint= NULL;
+ point_end= 0;
+ FOREACHpoint_i_(pointset) {
+ if (point) {
+ zzinc_(Zpartitionall);
+ qh_distplane (point, facet, &dist);
+ if (dist < distoutside)
+ SETelem_(pointset, point_end++)= point;
+ else {
+ qh num_outside++;
+ if (!bestpoint) {
+ bestpoint= point;
+ bestdist= dist;
+ }else if (dist > bestdist) {
+ qh_setappend (&facet->outsideset, bestpoint);
+ bestpoint= point;
+ bestdist= dist;
+ }else
+ qh_setappend (&facet->outsideset, point);
+ }
+ }
+ }
+ if (bestpoint) {
+ qh_setappend (&facet->outsideset, bestpoint);
+#if !qh_COMPUTEfurthest
+ facet->furthestdist= bestdist;
+#endif
+ }else
+ qh_setfree (&facet->outsideset);
+ qh_settruncate (pointset, point_end);
+ }
+ }
+ /* if !qh BESToutside, pointset contains points not assigned to outsideset */
+ if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
+ qh findbestnew= True;
+ FOREACHpoint_i_(pointset) {
+ if (point)
+ qh_partitionpoint(point, qh facet_list);
+ }
+ qh findbestnew= False;
+ }
+ zzadd_(Zpartitionall, zzval_(Zpartition));
+ zzval_(Zpartition)= 0;
+ qh_settempfree(&pointset);
+ if (qh IStracing >= 4)
+ qh_printfacetlist (qh facet_list, NULL, True);
+} /* partitionall */
+
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="partitioncoplanar">-</a>
+
+ qh_partitioncoplanar( point, facet, dist )
+ partition coplanar point to a facet
+ dist is distance from point to facet
+ if dist NULL,
+ searches for bestfacet and does nothing if inside
+ if qh.findbestnew set,
+ searches new facets instead of using qh_findbest()
+
+ returns:
+ qh.max_ouside updated
+ if qh.KEEPcoplanar or qh.KEEPinside
+ point assigned to best coplanarset
+
+ notes:
+ facet->maxoutside is updated at end by qh_check_maxout
+
+ design:
+ if dist undefined
+ find best facet for point
+ if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
+ exit
+ if keeping coplanar/nearinside/inside points
+ if point is above furthest coplanar point
+ append point to coplanar set (it is the new furthest)
+ update qh.max_outside
+ else
+ append point one before end of coplanar set
+ else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
+ and bestfacet is more than perpendicular to facet
+ repartition the point using qh_findbest() -- it may be put on an outsideset
+ else
+ update qh.max_outside
+*/
+void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist) {
+ facetT *bestfacet;
+ pointT *oldfurthest;
+ realT bestdist, dist2, angle;
+ int numpart= 0, oldfindbest;
+ boolT isoutside;
+
+ qh WAScoplanar= True;
+ if (!dist) {
+ if (qh findbestnew)
+ bestfacet= qh_findbestnew (point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
+ else
+ bestfacet= qh_findbest (point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY,
+ &bestdist, &isoutside, &numpart);
+ zinc_(Ztotpartcoplanar);
+ zzadd_(Zpartcoplanar, numpart);
+ if (!qh DELAUNAY && !qh KEEPinside) { /* for 'd', bestdist skips upperDelaunay facets */
+ if (qh KEEPnearinside) {
+ if (bestdist < -qh NEARinside) {
+ zinc_(Zcoplanarinside);
+ trace4((qh ferr, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
+ qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+ return;
+ }
+ }else if (bestdist < -qh MAXcoplanar) {
+ trace4((qh ferr, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
+ qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+ zinc_(Zcoplanarinside);
+ return;
+ }
+ }
+ }else {
+ bestfacet= facet;
+ bestdist= *dist;
+ }
+ if (bestdist > qh max_outside) {
+ if (!dist && facet != bestfacet) {
+ zinc_(Zpartangle);
+ angle= qh_getangle(facet->normal, bestfacet->normal);
+ if (angle < 0) {
+ /* typically due to deleted vertex and coplanar facets, e.g.,
+ RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
+ zinc_(Zpartflip);
+ trace2((qh ferr, "qh_partitioncoplanar: repartition point p%d from f%d. It is above flipped facet f%d dist %2.2g\n",
+ qh_pointid(point), facet->id, bestfacet->id, bestdist));
+ oldfindbest= qh findbestnew;
+ qh findbestnew= False;
+ qh_partitionpoint(point, bestfacet);
+ qh findbestnew= oldfindbest;
+ return;
+ }
+ }
+ qh max_outside= bestdist;
+ if (bestdist > qh TRACEdist) {
+ fprintf (qh ferr, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
+ qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
+ qh_errprint ("DISTANT", facet, bestfacet, NULL, NULL);
+ }
+ }
+ if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
+ oldfurthest= (pointT*)qh_setlast (bestfacet->coplanarset);
+ if (oldfurthest) {
+ zinc_(Zcomputefurthest);
+ qh_distplane (oldfurthest, bestfacet, &dist2);
+ }
+ if (!oldfurthest || dist2 < bestdist)
+ qh_setappend(&bestfacet->coplanarset, point);
+ else
+ qh_setappend2ndlast(&bestfacet->coplanarset, point);
+ }
+ trace4((qh ferr, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n",
+ qh_pointid(point), bestfacet->id, bestdist));
+} /* partitioncoplanar */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="partitionpoint">-</a>
+
+ qh_partitionpoint( point, facet )
+ assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
+ if qh.findbestnew
+ uses qh_findbestnew() to search all new facets
+ else
+ uses qh_findbest()
+
+ notes:
+ after qh_distplane(), this and qh_findbest() are most expensive in 3-d
+
+ design:
+ find best facet for point
+ (either exhaustive search of new facets or directed search from facet)
+ if qh.NARROWhull
+ retain coplanar and nearinside points as outside points
+ if point is outside bestfacet
+ if point above furthest point for bestfacet
+ append point to outside set (it becomes the new furthest)
+ if outside set was empty
+ move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
+ update bestfacet->furthestdist
+ else
+ append point one before end of outside set
+ else if point is coplanar to bestfacet
+ if keeping coplanar points or need to update qh.max_outside
+ partition coplanar point into bestfacet
+ else if near-inside point
+ partition as coplanar point into bestfacet
+ else is an inside point
+ if keeping inside points
+ partition as coplanar point into bestfacet
+*/
+void qh_partitionpoint (pointT *point, facetT *facet) {
+ realT bestdist;
+ boolT isoutside;
+ facetT *bestfacet;
+ int numpart;
+#if qh_COMPUTEfurthest
+ realT dist;
+#endif
+
+ if (qh findbestnew)
+ bestfacet= qh_findbestnew (point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
+ else
+ bestfacet= qh_findbest (point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
+ &bestdist, &isoutside, &numpart);
+ zinc_(Ztotpartition);
+ zzadd_(Zpartition, numpart);
+ if (qh NARROWhull) {
+ if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
+ qh_precision ("nearly incident point (narrow hull)");
+ if (qh KEEPnearinside) {
+ if (bestdist >= -qh NEARinside)
+ isoutside= True;
+ }else if (bestdist >= -qh MAXcoplanar)
+ isoutside= True;
+ }
+
+ if (isoutside) {
+ if (!bestfacet->outsideset
+ || !qh_setlast (bestfacet->outsideset)) {
+ qh_setappend(&(bestfacet->outsideset), point);
+ if (!bestfacet->newfacet) {
+ qh_removefacet (bestfacet); /* make sure it's after qh facet_next */
+ qh_appendfacet (bestfacet);
+ }
+#if !qh_COMPUTEfurthest
+ bestfacet->furthestdist= bestdist;
+#endif
+ }else {
+#if qh_COMPUTEfurthest
+ zinc_(Zcomputefurthest);
+ qh_distplane (oldfurthest, bestfacet, &dist);
+ if (dist < bestdist)
+ qh_setappend(&(bestfacet->outsideset), point);
+ else
+ qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#else
+ if (bestfacet->furthestdist < bestdist) {
+ qh_setappend(&(bestfacet->outsideset), point);
+ bestfacet->furthestdist= bestdist;
+ }else
+ qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#endif
+ }
+ qh num_outside++;
+ trace4((qh ferr, "qh_partitionpoint: point p%d is outside facet f%d new? %d(or narrowhull)\n",
+ qh_pointid(point), bestfacet->id, bestfacet->newfacet));
+ }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
+ zzinc_(Zcoplanarpart);
+ if (qh DELAUNAY)
+ qh_precision ("nearly incident point");
+ if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside)
+ qh_partitioncoplanar (point, bestfacet, &bestdist);
+ else {
+ trace4((qh ferr, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
+ qh_pointid(point), bestfacet->id));
+ }
+ }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
+ zinc_(Zpartnear);
+ qh_partitioncoplanar (point, bestfacet, &bestdist);
+ }else {
+ zinc_(Zpartinside);
+ trace4((qh ferr, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
+ qh_pointid(point), bestfacet->id, bestdist));
+ if (qh KEEPinside)
+ qh_partitioncoplanar (point, bestfacet, &bestdist);
+ }
+} /* partitionpoint */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="partitionvisible">-</a>
+
+ qh_partitionvisible( allpoints, numoutside )
+ partitions points in visible facets to qh.newfacet_list
+ qh.visible_list= visible facets
+ for visible facets
+ 1st neighbor (if any) points to a horizon facet or a new facet
+ if allpoints (not used),
+ repartitions coplanar points
+
+ returns:
+ updates outside sets and coplanar sets of qh.newfacet_list
+ updates qh.num_outside (count of outside points)
+
+ notes:
+ qh.findbest_notsharp should be clear (extra work if set)
+
+ design:
+ for all visible facets with outside set or coplanar set
+ select a newfacet for visible facet
+ if outside set
+ partition outside set into new facets
+ if coplanar set and keeping coplanar/near-inside/inside points
+ if allpoints
+ partition coplanar set into new facets, may be assigned outside
+ else
+ partition coplanar set into coplanar sets of new facets
+ for each deleted vertex
+ if allpoints
+ partition vertex into new facets, may be assigned outside
+ else
+ partition vertex into coplanar sets of new facets
+*/
+void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
+ facetT *visible, *newfacet;
+ pointT *point, **pointp;
+ int coplanar=0, size;
+ unsigned count;
+ vertexT *vertex, **vertexp;
+
+ if (qh ONLYmax)
+ maximize_(qh MINoutside, qh max_vertex);
+ *numoutside= 0;
+ FORALLvisible_facets {
+ if (!visible->outsideset && !visible->coplanarset)
+ continue;
+ newfacet= visible->f.replace;
+ count= 0;
+ while (newfacet && newfacet->visible) {
+ newfacet= newfacet->f.replace;
+ if (count++ > qh facet_id)
+ qh_infiniteloop (visible);
+ }
+ if (!newfacet)
+ newfacet= qh newfacet_list;
+ if (newfacet == qh facet_tail) {
+ fprintf (qh ferr, "qhull precision error (qh_partitionvisible): all new facets deleted as\n degenerate facets. Can not continue.\n");
+ qh_errexit (qh_ERRprec, NULL, NULL);
+ }
+ if (visible->outsideset) {
+ size= qh_setsize (visible->outsideset);
+ *numoutside += size;
+ qh num_outside -= size;
+ FOREACHpoint_(visible->outsideset)
+ qh_partitionpoint (point, newfacet);
+ }
+ if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
+ size= qh_setsize (visible->coplanarset);
+ coplanar += size;
+ FOREACHpoint_(visible->coplanarset) {
+ if (allpoints) /* not used */
+ qh_partitionpoint (point, newfacet);
+ else
+ qh_partitioncoplanar (point, newfacet, NULL);
+ }
+ }
+ }
+ FOREACHvertex_(qh del_vertices) {
+ if (vertex->point) {
+ if (allpoints) /* not used */
+ qh_partitionpoint (vertex->point, qh newfacet_list);
+ else
+ qh_partitioncoplanar (vertex->point, qh newfacet_list, NULL);
+ }
+ }
+ trace1((qh ferr,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
+} /* partitionvisible */
+
+
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="precision">-</a>
+
+ qh_precision( reason )
+ restart on precision errors if not merging and if 'QJn'
+*/
+void qh_precision (char *reason) {
+
+ if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
+ if (qh JOGGLEmax < REALmax/2) {
+ trace0((qh ferr, "qh_precision: qhull restart because of %s\n", reason));
+ longjmp(qh restartexit, qh_ERRprec);
+ }
+ }
+} /* qh_precision */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="printsummary">-</a>
+
+ qh_printsummary( fp )
+ prints summary to fp
+
+ notes:
+ not in io.c so that user_eg.c can prevent io.c from loading
+ qh_printsummary and qh_countfacets must match counts
+
+ design:
+ determine number of points, vertices, and coplanar points
+ print summary
+*/
+void qh_printsummary(FILE *fp) {
+ realT ratio, outerplane, innerplane;
+ float cpu;
+ int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
+ int goodused;
+ facetT *facet;
+ char *s;
+ int numdel= zzval_(Zdelvertextot);
+ int numtricoplanars= 0;
+
+ size= qh num_points + qh_setsize (qh other_points);
+ numvertices= qh num_vertices - qh_setsize (qh del_vertices);
+ id= qh_pointid (qh GOODpointp);
+ FORALLfacets {
+ if (facet->coplanarset)
+ numcoplanars += qh_setsize( facet->coplanarset);
+ if (facet->good) {
+ if (facet->simplicial) {
+ if (facet->keepcentrum && facet->tricoplanar)
+ numtricoplanars++;
+ }else if (qh_setsize(facet->vertices) != qh hull_dim)
+ nonsimplicial++;
+ }
+ }
+ if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+ size--;
+ if (qh STOPcone || qh STOPpoint)
+ fprintf (fp, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error.");
+ if (qh UPPERdelaunay)
+ goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
+ else if (qh DELAUNAY)
+ goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
+ else
+ goodused= qh num_good;
+ nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+ if (qh VORONOI) {
+ if (qh UPPERdelaunay)
+ fprintf (fp, "\n\
+Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ else
+ fprintf (fp, "\n\
+Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ fprintf(fp, " Number of Voronoi regions%s: %d\n",
+ qh ATinfinity ? " and at-infinity" : "", numvertices);
+ if (numdel)
+ fprintf(fp, " Total number of deleted points due to merging: %d\n", numdel);
+ if (numcoplanars - numdel > 0)
+ fprintf(fp, " Number of nearly incident points: %d\n", numcoplanars - numdel);
+ else if (size - numvertices - numdel > 0)
+ fprintf(fp, " Total number of nearly incident points: %d\n", size - numvertices - numdel);
+ fprintf(fp, " Number of%s Voronoi vertices: %d\n",
+ goodused ? " 'good'" : "", qh num_good);
+ if (nonsimplicial)
+ fprintf(fp, " Number of%s non-simplicial Voronoi vertices: %d\n",
+ goodused ? " 'good'" : "", nonsimplicial);
+ }else if (qh DELAUNAY) {
+ if (qh UPPERdelaunay)
+ fprintf (fp, "\n\
+Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ else
+ fprintf (fp, "\n\
+Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ fprintf(fp, " Number of input sites%s: %d\n",
+ qh ATinfinity ? " and at-infinity" : "", numvertices);
+ if (numdel)
+ fprintf(fp, " Total number of deleted points due to merging: %d\n", numdel);
+ if (numcoplanars - numdel > 0)
+ fprintf(fp, " Number of nearly incident points: %d\n", numcoplanars - numdel);
+ else if (size - numvertices - numdel > 0)
+ fprintf(fp, " Total number of nearly incident points: %d\n", size - numvertices - numdel);
+ fprintf(fp, " Number of%s Delaunay regions: %d\n",
+ goodused ? " 'good'" : "", qh num_good);
+ if (nonsimplicial)
+ fprintf(fp, " Number of%s non-simplicial Delaunay regions: %d\n",
+ goodused ? " 'good'" : "", nonsimplicial);
+ }else if (qh HALFspace) {
+ fprintf (fp, "\n\
+Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ fprintf(fp, " Number of halfspaces: %d\n", size);
+ fprintf(fp, " Number of non-redundant halfspaces: %d\n", numvertices);
+ if (numcoplanars) {
+ if (qh KEEPinside && qh KEEPcoplanar)
+ s= "similar and redundant";
+ else if (qh KEEPinside)
+ s= "redundant";
+ else
+ s= "similar";
+ fprintf(fp, " Number of %s halfspaces: %d\n", s, numcoplanars);
+ }
+ fprintf(fp, " Number of intersection points: %d\n", qh num_facets - qh num_visible);
+ if (goodused)
+ fprintf(fp, " Number of 'good' intersection points: %d\n", qh num_good);
+ if (nonsimplicial)
+ fprintf(fp, " Number of%s non-simplicial intersection points: %d\n",
+ goodused ? " 'good'" : "", nonsimplicial);
+ }else {
+ fprintf (fp, "\n\
+Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+ fprintf(fp, " Number of vertices: %d\n", numvertices);
+ if (numcoplanars) {
+ if (qh KEEPinside && qh KEEPcoplanar)
+ s= "coplanar and interior";
+ else if (qh KEEPinside)
+ s= "interior";
+ else
+ s= "coplanar";
+ fprintf(fp, " Number of %s points: %d\n", s, numcoplanars);
+ }
+ fprintf(fp, " Number of facets: %d\n", qh num_facets - qh num_visible);
+ if (goodused)
+ fprintf(fp, " Number of 'good' facets: %d\n", qh num_good);
+ if (nonsimplicial)
+ fprintf(fp, " Number of%s non-simplicial facets: %d\n",
+ goodused ? " 'good'" : "", nonsimplicial);
+ }
+ if (numtricoplanars)
+ fprintf(fp, " Number of triangulated facets: %d\n", numtricoplanars);
+ fprintf(fp, "\nStatistics for: %s | %s",
+ qh rbox_command, qh qhull_command);
+ if (qh ROTATErandom != INT_MIN)
+ fprintf(fp, " QR%d\n\n", qh ROTATErandom);
+ else
+ fprintf(fp, "\n\n");
+ fprintf(fp, " Number of points processed: %d\n", zzval_(Zprocessed));
+ fprintf(fp, " Number of hyperplanes created: %d\n", zzval_(Zsetplane));
+ if (qh DELAUNAY)
+ fprintf(fp, " Number of facets in hull: %d\n", qh num_facets - qh num_visible);
+ fprintf(fp, " Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
+ zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
+#if 0 /* NOTE: must print before printstatistics() */
+ {realT stddev, ave;
+ fprintf(fp, " average new facet balance: %2.2g\n",
+ wval_(Wnewbalance)/zval_(Zprocessed));
+ stddev= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance),
+ wval_(Wnewbalance2), &ave);
+ fprintf(fp, " new facet standard deviation: %2.2g\n", stddev);
+ fprintf(fp, " average partition balance: %2.2g\n",
+ wval_(Wpbalance)/zval_(Zpbalance));
+ stddev= qh_stddev (zval_(Zpbalance), wval_(Wpbalance),
+ wval_(Wpbalance2), &ave);
+ fprintf(fp, " partition standard deviation: %2.2g\n", stddev);
+ }
+#endif
+ if (nummerged) {
+ fprintf(fp," Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
+ zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
+ zzval_(Zdistzero));
+ fprintf(fp," Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
+ fprintf(fp," Number of merged facets: %d\n", nummerged);
+ }
+ if (!qh RANDOMoutside && qh QHULLfinished) {
+ cpu= qh hulltime;
+ cpu /= qh_SECticks;
+ wval_(Wcpu)= cpu;
+ fprintf (fp, " CPU seconds to compute hull (after input): %2.4g\n", cpu);
+ }
+ if (qh RERUN) {
+ if (!qh PREmerge && !qh MERGEexact)
+ fprintf(fp, " Percentage of runs with precision errors: %4.1f\n",
+ zzval_(Zretry)*100.0/qh build_cnt); /* careful of order */
+ }else if (qh JOGGLEmax < REALmax/2) {
+ if (zzval_(Zretry))
+ fprintf(fp, " After %d retries, input joggled by: %2.2g\n",
+ zzval_(Zretry), qh JOGGLEmax);
+ else
+ fprintf(fp, " Input joggled by: %2.2g\n", qh JOGGLEmax);
+ }
+ if (qh totarea != 0.0)
+ fprintf(fp, " %s facet area: %2.8g\n",
+ zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
+ if (qh totvol != 0.0)
+ fprintf(fp, " %s volume: %2.8g\n",
+ zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
+ if (qh MERGING) {
+ qh_outerinner (NULL, &outerplane, &innerplane);
+ if (outerplane > 2 * qh DISTround) {
+ fprintf(fp, " Maximum distance of %spoint above facet: %2.2g",
+ (qh QHULLfinished ? "" : "merged "), outerplane);
+ ratio= outerplane/(qh ONEmerge + qh DISTround);
+ /* don't report ratio if MINoutside is large */
+ if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
+ fprintf (fp, " (%.1fx)\n", ratio);
+ else
+ fprintf (fp, "\n");
+ }
+ if (innerplane < -2 * qh DISTround) {
+ fprintf(fp, " Maximum distance of %svertex below facet: %2.2g",
+ (qh QHULLfinished ? "" : "merged "), innerplane);
+ ratio= -innerplane/(qh ONEmerge+qh DISTround);
+ if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
+ fprintf (fp, " (%.1fx)\n", ratio);
+ else
+ fprintf (fp, "\n");
+ }
+ }
+ fprintf(fp, "\n");
+} /* printsummary */
+
+
diff --git a/extern/qhull/src/qhull.h b/extern/qhull/src/qhull.h
new file mode 100644
index 00000000000..896ec1e9c18
--- /dev/null
+++ b/extern/qhull/src/qhull.h
@@ -0,0 +1,1048 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhull.h
+ user-level header file for using qhull.a library
+
+ see qh-qhull.htm, qhull_a.h
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ NOTE: access to qh_qh is via the 'qh' macro. This allows
+ qh_qh to be either a pointer or a structure. An example
+ of using qh is "qh DROPdim" which accesses the DROPdim
+ field of qh_qh. Similarly, access to qh_qhstat is via
+ the 'qhstat' macro.
+
+ includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
+
+ use mem.h for mem.c
+ use qset.h for qset.c
+
+ see unix.c for an example of using qhull.h
+
+ recompile qhull if you change this file
+*/
+
+#ifndef qhDEFqhull
+#define qhDEFqhull 1
+
+/*=========================== -included files ==============*/
+
+#include <setjmp.h>
+#include <float.h>
+#include <time.h>
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <Desk.h>
+#endif
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if !_MSC_VER
+#error Neither __STDC__ nor __cplusplus is defined. Please use strict ANSI C or C++ to compile
+#error Qhull. You may need to turn off compiler extensions in your project configuration. If
+#error your compiler is a standard C compiler, you can delete this warning from qhull.h
+#endif
+#endif
+#endif
+
+#include "user.h" /* user defineable constants */
+
+/*============ constants and basic types ====================*/
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_VERSION">-</a>
+
+ qh_VERSION
+ version string by year and date
+
+ the revision increases on code changes only
+
+ notes:
+ change date: Changes.txt, Announce.txt, README.txt, qhull.man
+ qhull-news.html, Eudora signatures,
+ change version: README.txt, qhull.html, file_id.diz, Makefile
+ change year: Copying.txt
+ check download size
+ recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
+ make copy of qhull-news.html as qh-news.htm
+*/
+
+#define qh_VERSION "2002.1 2002/8/20"
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="coordT">-</a>
+
+ coordT
+ coordinates and coefficients are stored as realT (i.e., double)
+
+ notes:
+ could use 'float' for data and 'double' for calculations (realT vs. coordT)
+ This requires many type casts, and adjusted error bounds.
+ Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*-<a href="qh-geom.htm#TOC"
+ >--------------------------------</a><a name="pointT">-</a>
+
+ pointT
+ a point is an array of DIM3 coordinates
+*/
+#define pointT coordT
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="flagT">-</a>
+
+ flagT
+ Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="boolT">-</a>
+
+ boolT
+ boolean value, either True or False
+
+ notes:
+ needed for portability
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="CENTERtype">-</a>
+
+ qh_CENTER
+ to distinguish facet->center
+*/
+typedef enum
+{
+ qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
+}
+qh_CENTER;
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_PRINT">-</a>
+
+ qh_PRINT
+ output formats for printing (qh.PRINTout).
+ 'Fa' 'FV' 'Fc' 'FC'
+
+
+ notes:
+ some of these names are similar to qh names. The similar names are only
+ used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0,
+ qh_PRINTarea, qh_PRINTaverage, /* 'Fa' 'FV' 'Fc' 'FC' */
+ qh_PRINTcoplanars, qh_PRINTcentrums,
+ qh_PRINTfacets, qh_PRINTfacets_xridge, /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+ qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
+ qh_PRINTnormals, qh_PRINTouter, /* 'n' 'Fo' 'i' 'm' 'Fm' 'o' */
+ qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
+ qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+ qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
+ qh_PRINTsummary, qh_PRINTtriangles, /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+ qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+ qh_PRINTEND} qh_PRINT;
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_ALL">-</a>
+
+ qh_ALL
+ argument flag for selecting everything
+*/
+#define qh_ALL True
+#define qh_NOupper True /* argument for qh_findbest */
+#define qh_IScheckmax True /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets True /* argument for qh_findbest */
+#define qh_RESETvisible True /* argument for qh_resetlists */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="qh_ERR">-</a>
+
+ qh_ERR
+ Qhull exit codes, for indicating errors
+*/
+#define qh_ERRnone 0 /* no error occurred during qhull */
+#define qh_ERRinput 1 /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data */
+#define qh_ERRprec 3 /* precision error */
+#define qh_ERRmem 4 /* insufficient memory, matches mem.h */
+#define qh_ERRqhull 5 /* internal error detected, matches mem.h */
+
+/* ============ -structures- ====================
+ each of the following structures is defined by a typedef
+ all realT and coordT fields occur at the beginning of a structure
+ (otherwise space may be wasted due to alignment)
+ define all flags together and pack into 32-bit number
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT; /* defined in qset.h */
+#endif
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="facetT">-</a>
+
+ facetT
+ defines a facet
+
+ notes:
+ qhull() generates the hull as a list of facets.
+
+ topological information:
+ f.previous,next doubly-linked list of facets
+ f.vertices set of vertices
+ f.ridges set of ridges
+ f.neighbors set of neighbors
+ f.toporient True if facet has top-orientation (else bottom)
+
+ geometric information:
+ f.offset,normal hyperplane equation
+ f.maxoutside offset to outer plane -- all points inside
+ f.center centrum for testing convexity
+ f.simplicial True if facet is simplicial
+ f.flipped True if facet does not include qh.interior_point
+
+ for constructing hull:
+ f.visible True if facet on list of visible facets (will be deleted)
+ f.newfacet True if facet on list of newly created facets
+ f.coplanarset set of points coplanar with this facet
+ (includes near-inside points for later testing)
+ f.outsideset set of points outside of this facet
+ f.furthestdist distance to furthest point of outside set
+ f.visitid marks visited facets during a loop
+ f.replace replacement facet for to-be-deleted, visible facets
+ f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+ see below for other flags and fields
+*/
+struct facetT {
+#if !qh_COMPUTEfurthest
+ coordT furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+ coordT maxoutside; /* max computed distance of point to facet
+ Before QHULLfinished this is an approximation
+ since maxdist not always set for mergefacet
+ Actual outer plane is +DISTround and
+ computed outer plane is +2*DISTround */
+#endif
+ coordT offset; /* exact offset of hyperplane from origin */
+ coordT *normal; /* normal of hyperplane, hull_dim coefficients */
+ /* if tricoplanar, shared with a neighbor */
+ union { /* in order of testing */
+ realT area; /* area of facet, only in io.c if ->isarea */
+ facetT *replace; /* replacement facet if ->visible and NEWfacets
+ is NULL only if qh_mergedegen_redundant or interior */
+ facetT *samecycle; /* cycle of facets from the same visible/horizon intersection,
+ if ->newfacet */
+ facetT *newcycle; /* in horizon facet, current samecycle of new facets */
+ facetT *trivisible; /* visible facet for ->tricoplanar facets during qh_triangulate() */
+ facetT *triowner; /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+ }f;
+ coordT *center; /* centrum for convexity, qh CENTERtype == qh_AScentrum */
+ /* Voronoi center, qh CENTERtype == qh_ASvoronoi */
+ /* if tricoplanar, shared with a neighbor */
+ facetT *previous; /* previous facet in the facet_list */
+ facetT *next; /* next facet in the facet_list */
+ setT *vertices; /* vertices for this facet, inverse sorted by ID
+ if simplicial, 1st vertex was apex/furthest */
+ setT *ridges; /* explicit ridges for nonsimplicial facets.
+ for simplicial facets, neighbors defines ridge */
+ setT *neighbors; /* neighbors of the facet. If simplicial, the kth
+ neighbor is opposite the kth vertex, and the first
+ neighbor is the horizon facet for the first vertex*/
+ setT *outsideset; /* set of points outside this facet
+ if non-empty, last point is furthest
+ if NARROWhull, includes coplanars for partitioning*/
+ setT *coplanarset; /* set of points coplanar with this facet
+ > qh.min_vertex and <= facet->max_outside
+ a point is assigned to the furthest facet
+ if non-empty, last point is furthest away */
+ unsigned visitid; /* visit_id, for visiting all neighbors,
+ all uses are independent */
+ unsigned id; /* unique identifier from qh facet_id */
+ unsigned nummerge:9; /* number of merges */
+#define qh_MAXnummerge 511 /* 2^9-1, 32 flags total, see "flags:" in io.c */
+ flagT tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+ /* all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+ /* all tricoplanars share the same apex */
+ /* if ->degenerate, does not span facet (one logical ridge) */
+ /* one tricoplanar has ->keepcentrum and ->coplanarset */
+ /* during qh_triangulate, f.trivisible points to original facet */
+ flagT newfacet:1; /* True if facet on qh newfacet_list (new or merged) */
+ flagT visible:1; /* True if visible facet (will be deleted) */
+ flagT toporient:1; /* True if created with top orientation
+ after merging, use ridge orientation */
+ flagT simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+ flagT seen:1; /* used to perform operations only once, like visitid */
+ flagT seen2:1; /* used to perform operations only once, like visitid */
+ flagT flipped:1; /* True if facet is flipped */
+ flagT upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+ flagT notfurthest:1; /* True if last point of outsideset is not furthest*/
+
+/*-------- flags primarily for output ---------*/
+ flagT good:1; /* True if a facet marked good for output */
+ flagT isarea:1; /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+ flagT dupridge:1; /* True if duplicate ridge in facet */
+ flagT mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
+ ->normal defined (also defined for mergeridge2) */
+ flagT mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
+ flagT coplanar:1; /* True if horizon facet is coplanar at last use */
+ flagT mergehorizon:1; /* True if will merge into horizon (->coplanar) */
+ flagT cycledone:1;/* True if mergecycle_all already done */
+ flagT tested:1; /* True if facet convexity has been tested (false after merge */
+ flagT keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
+ flagT newmerge:1; /* True if facet is newly merged for reducevertices */
+ flagT degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+ flagT redundant:1; /* True if facet is redundant (degen_mergeset) */
+};
+
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="ridgeT">-</a>
+
+ ridgeT
+ defines a ridge
+
+ notes:
+ a ridge is DIM3-1 simplex between two neighboring facets. If the
+ facets are non-simplicial, there may be more than one ridge between
+ two facets. E.G. a 4-d hypercube has two triangles between each pair
+ of neighboring facets.
+
+ topological information:
+ vertices a set of vertices
+ top,bottom neighboring facets with orientation
+
+ geometric information:
+ tested True if ridge is clearly convex
+ nonconvex True if ridge is non-convex
+*/
+struct ridgeT {
+ setT *vertices; /* vertices belonging to this ridge, inverse sorted by ID
+ NULL if a degen ridge (matchsame) */
+ facetT *top; /* top facet this ridge is part of */
+ facetT *bottom; /* bottom facet this ridge is part of */
+ unsigned id:24; /* unique identifier, =>room for 8 flags */
+ flagT seen:1; /* used to perform operations only once */
+ flagT tested:1; /* True when ridge is tested for convexity */
+ flagT nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+ only one ridge between neighbors may have nonconvex */
+};
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="vertexT">-</a>
+
+ vertexT
+ defines a vertex
+
+ topological information:
+ next,previous doubly-linked list of all vertices
+ neighbors set of adjacent facets (only if qh.VERTEXneighbors)
+
+ geometric information:
+ point array of DIM3 coordinates
+*/
+struct vertexT {
+ vertexT *next; /* next vertex in vertex_list */
+ vertexT *previous; /* previous vertex in vertex_list */
+ pointT *point; /* hull_dim coordinates (coordT) */
+ setT *neighbors; /* neighboring facets of vertex, qh_vertexneighbors()
+ inits in io.c or after first merge */
+ unsigned visitid; /* for use with qh vertex_visit */
+ unsigned id:24; /* unique identifier, =>room for 8 flags */
+ flagT seen:1; /* used to perform operations only once */
+ flagT seen2:1; /* another seen flag */
+ flagT delridge:1; /* vertex was part of a deleted ridge */
+ flagT deleted:1; /* true if vertex on qh del_vertices */
+ flagT newlist:1; /* true if vertex on qh newvertex_list */
+};
+
+/*======= -global variables -qh ============================*/
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh">-</a>
+
+ qh
+ all global variables for qhull are in qh, qhmem, and qhstat
+
+ notes:
+ qhmem is defined in mem.h and qhstat is defined in stat.h
+ access to qh_qh is via the "qh" macro. See qh_QHpointer in user.h
+*/
+typedef struct qhT qhT;
+#if qh_QHpointer
+#define qh qh_qh->
+extern qhT *qh_qh; /* allocated in global.c */
+#else
+#define qh qh_qh.
+extern qhT qh_qh;
+#endif
+
+struct qhT {
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-const">-</a>
+
+ qh constants
+ configuration flags and constants for Qhull
+
+ notes:
+ The user configures Qhull by defining flags. They are
+ copied into qh by qh_setflags(). qh-quick.htm#options defines the flags.
+*/
+ boolT ALLpoints; /* true 'Qs' if search all points for initial simplex */
+ boolT ANGLEmerge; /* true 'Qa' if sort potential merges by angle */
+ boolT APPROXhull; /* true 'Wn' if MINoutside set */
+ realT MINoutside; /* 'Wn' min. distance for an outside point */
+ boolT ATinfinity; /* true 'Qz' if point num_points-1 is "at-infinity"
+ for improving precision in Delaunay triangulations */
+ boolT AVOIDold; /* true 'Q4' if avoid old->new merges */
+ boolT BESToutside; /* true 'Qf' if partition points into best outsideset */
+ boolT CDDinput; /* true 'Pc' if input uses CDD format (1.0/offset first) */
+ boolT CDDoutput; /* true 'PC' if print normals in CDD format (offset first) */
+ boolT CHECKfrequently; /* true 'Tc' if checking frequently */
+ realT premerge_cos; /* 'A-n' cos_max when pre merging */
+ realT postmerge_cos; /* 'An' cos_max when post merging */
+ boolT DELAUNAY; /* true 'd' if computing DELAUNAY triangulation */
+ boolT DOintersections; /* true 'Gh' if print hyperplane intersections */
+ int DROPdim; /* drops dim 'GDn' for 4-d -> 3-d output */
+ boolT FORCEoutput; /* true 'Po' if forcing output despite degeneracies */
+ int GOODpoint; /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
+ pointT *GOODpointp; /* the actual point */
+ boolT GOODthreshold; /* true if qh lower_threshold/upper_threshold defined
+ false if qh SPLITthreshold */
+ int GOODvertex; /* 1+n, good facet if vertex for point n */
+ pointT *GOODvertexp; /* the actual point */
+ boolT HALFspace; /* true 'Hn,n,n' if halfspace intersection */
+ int IStracing; /* trace execution, 0=none, 1=least, 4=most, -1=events */
+ int KEEParea; /* 'PAn' number of largest facets to keep */
+ boolT KEEPcoplanar; /* true 'Qc' if keeping nearest facet for coplanar points */
+ boolT KEEPinside; /* true 'Qi' if keeping nearest facet for inside points
+ set automatically if 'd Qc' */
+ int KEEPmerge; /* 'PMn' number of facets to keep with most merges */
+ realT KEEPminArea; /* 'PFn' minimum facet area to keep */
+ realT MAXcoplanar; /* 'Un' max distance below a facet to be coplanar*/
+ boolT MERGEexact; /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
+ boolT MERGEindependent; /* true 'Q2' if merging independent sets */
+ boolT MERGING; /* true if exact-, pre- or post-merging, with angle and centrum tests */
+ realT premerge_centrum; /* 'C-n' centrum_radius when pre merging. Default is round-off */
+ realT postmerge_centrum; /* 'Cn' centrum_radius when post merging. Default is round-off */
+ boolT MERGEvertices; /* true 'Q3' if merging redundant vertices */
+ realT MINvisible; /* 'Vn' min. distance for a facet to be visible */
+ boolT NOnarrow; /* true 'Q10' if no special processing for narrow distributions */
+ boolT NOnearinside; /* true 'Q8' if ignore near-inside points when partitioning */
+ boolT NOpremerge; /* true 'Q0' if no defaults for C-0 or Qx */
+ boolT ONLYgood; /* true 'Qg' if process points with good visible or horizon facets */
+ boolT ONLYmax; /* true 'Qm' if only process points that increase max_outside */
+ boolT PICKfurthest; /* true 'Q9' if process furthest of furthest points*/
+ boolT POSTmerge; /* true if merging after buildhull (Cn or An) */
+ boolT PREmerge; /* true if merging during buildhull (C-n or A-n) */
+ /* NOTE: some of these names are similar to qh_PRINT names */
+ boolT PRINTcentrums; /* true 'Gc' if printing centrums */
+ boolT PRINTcoplanar; /* true 'Gp' if printing coplanar points */
+ int PRINTdim; /* print dimension for Geomview output */
+ boolT PRINTdots; /* true 'Ga' if printing all points as dots */
+ boolT PRINTgood; /* true 'Pg' if printing good facets */
+ boolT PRINTinner; /* true 'Gi' if printing inner planes */
+ boolT PRINTneighbors; /* true 'PG' if printing neighbors of good facets */
+ boolT PRINTnoplanes; /* true 'Gn' if printing no planes */
+ boolT PRINToptions1st; /* true 'FO' if printing options to stderr */
+ boolT PRINTouter; /* true 'Go' if printing outer planes */
+ boolT PRINTprecision; /* false 'Pp' if not reporting precision problems */
+ qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+ boolT PRINTridges; /* true 'Gr' if print ridges */
+ boolT PRINTspheres; /* true 'Gv' if print vertices as spheres */
+ boolT PRINTstatistics; /* true 'Ts' if printing statistics to stderr */
+ boolT PRINTsummary; /* true 's' if printing summary to stderr */
+ boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+ boolT PROJECTdelaunay; /* true if DELAUNAY, no readpoints() and
+ need projectinput() for Delaunay in qh_init_B */
+ int PROJECTinput; /* number of projected dimensions 'bn:0Bn:0' */
+ boolT QUICKhelp; /* true if quick help message for degen input */
+ boolT RANDOMdist; /* true if randomly change distplane and setfacetplane */
+ realT RANDOMfactor; /* maximum random perturbation */
+ realT RANDOMa; /* qh_randomfactor is randr * RANDOMa + RANDOMb */
+ realT RANDOMb;
+ boolT RANDOMoutside; /* true if select a random outside point */
+ int REPORTfreq; /* buildtracing reports every n facets */
+ int REPORTfreq2; /* tracemerging reports every REPORTfreq/2 facets */
+ int RERUN; /* 'TRn' rerun qhull n times (qh.build_cnt) */
+ int ROTATErandom; /* 'QRn' seed, 0 time, >= rotate input */
+ boolT SCALEinput; /* true 'Qbk' if scaling input */
+ boolT SCALElast; /* true 'Qbb' if scale last coord to max prev coord */
+ boolT SETroundoff; /* true 'E' if qh DISTround is predefined */
+ boolT SKIPcheckmax; /* true 'Q5' if skip qh_check_maxout */
+ boolT SKIPconvex; /* true 'Q6' if skip convexity testing during pre-merge */
+ boolT SPLITthresholds; /* true if upper_/lower_threshold defines a region
+ used only for printing (not for qh ONLYgood) */
+ int STOPcone; /* 'TCn' 1+n for stopping after cone for point n*/
+ /* also used by qh_build_withresart for err exit*/
+ int STOPpoint; /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+ adding point n */
+ int TESTpoints; /* 'QTn' num of test points after qh.num_points. Test points always coplanar. */
+ boolT TESTvneighbors; /* true 'Qv' if test vertex neighbors at end */
+ int TRACElevel; /* 'Tn' conditional IStracing level */
+ int TRACElastrun; /* qh.TRACElevel applies to last qh.RERUN */
+ int TRACEpoint; /* 'TPn' start tracing when point n is a vertex */
+ realT TRACEdist; /* 'TWn' start tracing when merge distance too big */
+ int TRACEmerge; /* 'TMn' start tracing before this merge */
+ boolT TRIangulate; /* true 'Qt' if triangulate non-simplicial facets */
+ boolT TRInormals; /* true 'Q11' if triangulate duplicates normals (sets Qt) */
+ boolT UPPERdelaunay; /* true 'Qu' if computing furthest-site Delaunay */
+ boolT VERIFYoutput; /* true 'Tv' if verify output at end of qhull */
+ boolT VIRTUALmemory; /* true 'Q7' if depth-first processing in buildhull */
+ boolT VORONOI; /* true 'v' if computing Voronoi diagram */
+
+ /*--------input constants ---------*/
+ realT AREAfactor; /* 1/(hull_dim-1)! for converting det's to area */
+ boolT DOcheckmax; /* true if calling qh_check_maxout (qh_initqhull_globals) */
+ char *feasible_string; /* feasible point 'Hn,n,n' for halfspace intersection */
+ coordT *feasible_point; /* as coordinates, both malloc'd */
+ boolT GETarea; /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
+ boolT KEEPnearinside; /* true if near-inside points in coplanarset */
+ int hull_dim; /* dimension of hull, set by initbuffers */
+ int input_dim; /* dimension of input, set by initbuffers */
+ int num_points; /* number of input points */
+ pointT *first_point; /* array of input points, see POINTSmalloc */
+ boolT POINTSmalloc; /* true if qh first_point/num_points allocated */
+ pointT *input_points; /* copy of original qh.first_point for input points for qh_joggleinput */
+ boolT input_malloc; /* true if qh input_points malloc'd */
+ char qhull_command[256];/* command line that invoked this program */
+ char rbox_command[256]; /* command line that produced the input points */
+ char qhull_options[512];/* descriptive list of options */
+ int qhull_optionlen; /* length of last line */
+ int qhull_optionsiz; /* size of qhull_options before qh_initbuild */
+ boolT VERTEXneighbors; /* true if maintaining vertex neighbors */
+ boolT ZEROcentrum; /* true if 'C-0' or 'C-0 Qx'. sets ZEROall_ok */
+ realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+ must set either GOODthreshold or SPLITthreshold
+ if Delaunay, default is 0.0 for upper envelope */
+ realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+ realT *upper_bound; /* scale point[k] to new upper bound */
+ realT *lower_bound; /* scale point[k] to new lower bound
+ project if both upper_ and lower_bound == 0 */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-prec">-</a>
+
+ qh precision constants
+ precision constants for Qhull
+
+ notes:
+ qh_detroundoff() computes the maximum roundoff error for distance
+ and other computations. It also sets default values for the
+ qh constants above.
+*/
+ realT ANGLEround; /* max round off error for angles */
+ realT centrum_radius; /* max centrum radius for convexity (roundoff added) */
+ realT cos_max; /* max cosine for convexity (roundoff added) */
+ realT DISTround; /* max round off error for distances, 'E' overrides */
+ realT MAXabs_coord; /* max absolute coordinate */
+ realT MAXlastcoord; /* max last coordinate for qh_scalelast */
+ realT MAXsumcoord; /* max sum of coordinates */
+ realT MAXwidth; /* max rectilinear width of point coordinates */
+ realT MINdenom_1; /* min. abs. value for 1/x */
+ realT MINdenom; /* use divzero if denominator < MINdenom */
+ realT MINdenom_1_2; /* min. abs. val for 1/x that allows normalization */
+ realT MINdenom_2; /* use divzero if denominator < MINdenom_2 */
+ realT MINlastcoord; /* min. last coordinate for qh_scalelast */
+ boolT NARROWhull; /* set in qh_initialhull if angle < qh_MAXnarrow */
+ realT *NEARzero; /* hull_dim array for near zero in gausselim */
+ realT NEARinside; /* keep points for qh_check_maxout if close to facet */
+ realT ONEmerge; /* max distance for merging simplicial facets */
+ realT outside_err; /* application's epsilon for coplanar points
+ qh_check_bestdist() qh_check_points() reports error if point outside */
+ realT WIDEfacet; /* size of wide facet for skipping ridge in
+ area computation and locking centrum */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-intern">-</a>
+
+ qh internal constants
+ internal constants for Qhull
+*/
+ char qhull[sizeof("qhull")]; /* for checking ownership */
+ void *old_stat; /* pointer to saved qh_qhstat, qh_save_qhull */
+ jmp_buf errexit; /* exit label for qh_errexit, defined by setjmp() */
+ char jmpXtra[40]; /* extra bytes in case jmp_buf is defined wrong by compiler */
+ jmp_buf restartexit; /* restart label for qh_errexit, defined by setjmp() */
+ char jmpXtra2[40]; /* extra bytes in case jmp_buf is defined wrong by compiler*/
+ FILE *fin; /* pointer to input file, init by qh_meminit */
+ FILE *fout; /* pointer to output file */
+ FILE *ferr; /* pointer to error file */
+ pointT *interior_point; /* center point of the initial simplex*/
+ int normal_size; /* size in bytes for facet normals and point coords*/
+ int center_size; /* size in bytes for Voronoi centers */
+ int TEMPsize; /* size for small, temporary sets (in quick mem) */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-lists">-</a>
+
+ qh facet and vertex lists
+ defines lists of facets, new facets, visible facets, vertices, and
+ new vertices. Includes counts, next ids, and trace ids.
+ see:
+ qh_resetlists()
+*/
+ facetT *facet_list; /* first facet */
+ facetT *facet_tail; /* end of facet_list (dummy facet) */
+ facetT *facet_next; /* next facet for buildhull()
+ previous facets do not have outside sets
+ NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+ facetT *newfacet_list; /* list of new facets to end of facet_list */
+ facetT *visible_list; /* list of visible facets preceeding newfacet_list,
+ facet->visible set */
+ int num_visible; /* current number of visible facets */
+ unsigned tracefacet_id; /* set at init, then can print whenever */
+ facetT *tracefacet; /* set in newfacet/mergefacet, undone in delfacet*/
+ unsigned tracevertex_id; /* set at buildtracing, can print whenever */
+ vertexT *tracevertex; /* set in newvertex, undone in delvertex*/
+ vertexT *vertex_list; /* list of all vertices, to vertex_tail */
+ vertexT *vertex_tail; /* end of vertex_list (dummy vertex) */
+ vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+ all vertices have 'newlist' set */
+ int num_facets; /* number of facets in facet_list
+ includes visble faces (num_visible) */
+ int num_vertices; /* number of vertices in facet_list */
+ int num_outside; /* number of points in outsidesets (for tracing and RANDOMoutside)
+ includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+ int num_good; /* number of good facets (after findgood_all) */
+ unsigned facet_id; /* ID of next, new facet from newfacet() */
+ unsigned ridge_id; /* ID of next, new ridge from newridge() */
+ unsigned vertex_id; /* ID of next, new vertex from newvertex() */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-var">-</a>
+
+ qh global variables
+ defines minimum and maximum distances, next visit ids, several flags,
+ and other global variables.
+ initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+ unsigned long hulltime; /* ignore time to set up input and randomize */
+ /* use unsigned to avoid wrap-around errors */
+ boolT ALLOWrestart; /* true if qh_precision can use qh.restartexit */
+ int build_cnt; /* number of calls to qh_initbuild */
+ qh_CENTER CENTERtype; /* current type of facet->center, qh_CENTER */
+ int furthest_id; /* pointid of furthest point, for tracing */
+ facetT *GOODclosest; /* closest facet to GOODthreshold in qh_findgood */
+ realT JOGGLEmax; /* set 'QJn' if randomly joggle input */
+ boolT maxoutdone; /* set qh_check_maxout(), cleared by qh_addpoint() */
+ realT max_outside; /* maximum distance from a point to a facet,
+ before roundoff, not simplicial vertices
+ actual outer plane is +DISTround and
+ computed outer plane is +2*DISTround */
+ realT max_vertex; /* maximum distance (>0) from vertex to a facet,
+ before roundoff, due to a merge */
+ realT min_vertex; /* minimum distance (<0) from vertex to a facet,
+ before roundoff, due to a merge
+ if qh.JOGGLEmax, qh_makenewplanes sets it
+ recomputed if qh.DOcheckmax, default -qh.DISTround */
+ boolT NEWfacets; /* true while visible facets invalid due to new or merge
+ from makecone/attachnewfacets to deletevisible */
+ boolT findbestnew; /* true if partitioning calls qh_findbestnew */
+ boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+ boolT NOerrexit; /* true if qh.errexit is not available */
+ realT PRINTcradius; /* radius for printing centrums */
+ realT PRINTradius; /* radius for printing vertex spheres and points */
+ boolT POSTmerging; /* true when post merging */
+ int printoutvar; /* temporary variable for qh_printbegin, etc. */
+ int printoutnum; /* number of facets printed */
+ boolT QHULLfinished; /* True after qhull() is finished */
+ realT totarea; /* 'FA': total facet area computed by qh_getarea */
+ realT totvol; /* 'FA': total volume computed by qh_getarea */
+ unsigned int visit_id; /* unique ID for searching neighborhoods, */
+ unsigned int vertex_visit; /* unique ID for searching vertices */
+ boolT ZEROall_ok; /* True if qh_checkzero always succeeds */
+ boolT WAScoplanar; /* True if qh_partitioncoplanar (qh_check_maxout) */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-set">-</a>
+
+ qh global sets
+ defines sets for merging, initial simplex, hashing, extra input points,
+ and deleted vertices
+*/
+ setT *facet_mergeset; /* temporary set of merges to be done */
+ setT *degen_mergeset; /* temporary set of degenerate and redundant merges */
+ setT *hash_table; /* hash table for matching ridges in qh_matchfacets
+ size is setsize() */
+ setT *other_points; /* additional points (first is qh interior_point) */
+ setT *del_vertices; /* vertices to partition and delete with visible
+ facets. Have deleted set for checkfacet */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-buf">-</a>
+
+ qh global buffers
+ defines buffers for maxtrix operations, input, and error messages
+*/
+ coordT *gm_matrix; /* (dim+1)Xdim matrix for geom.c */
+ coordT **gm_row; /* array of gm_matrix rows */
+ char* line; /* malloc'd input line of maxline+1 chars */
+ int maxline;
+ coordT *half_space; /* malloc'd input array for halfspace (qh normal_size+coordT) */
+ coordT *temp_malloc; /* malloc'd input array for points */
+
+/*-<a href="qh-globa.htm#TOC"
+ >--------------------------------</a><a name="qh-static">-</a>
+
+ qh static variables
+ defines static variables for individual functions
+
+ notes:
+ do not use 'static' within a function. Multiple instances of qhull
+ may exist.
+
+ do not assume zero initialization, 'QPn' may cause a restart
+*/
+ boolT ERREXITcalled; /* true during errexit (prevents duplicate calls */
+ boolT firstcentrum; /* for qh_printcentrum */
+ realT last_low; /* qh_scalelast parameters for qh_setdelaunay */
+ realT last_high;
+ realT last_newhigh;
+ unsigned lastreport; /* for qh_buildtracing */
+ int mergereport; /* for qh_tracemerging */
+ boolT old_randomdist; /* save RANDOMdist when io, tracing, or statistics */
+ int ridgeoutnum; /* number of ridges in 4OFF output */
+ void *old_qhstat; /* for saving qh_qhstat in save_qhull() */
+ setT *old_tempstack; /* for saving qhmem.tempstack in save_qhull */
+ setT *coplanarset; /* set of coplanar facets for searching qh_findbesthorizon() */
+};
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="otherfacet_">-</a>
+
+ otherfacet_(ridge, facet)
+ return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+ (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="getid_">-</a>
+
+ getid_(p)
+ return ID for facet, ridge, or vertex
+ return MAXINT if NULL (-1 causes type conversion error )
+*/
+#define getid_(p) ((p) ? (p)->id : -1)
+
+/*============== FORALL macros ===================*/
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLfacets">-</a>
+
+ FORALLfacets { ... }
+ assign 'facet' to each facet in qh.facet_list
+
+ notes:
+ uses 'facetT *facet;'
+ assumes last facet is a sentinel
+
+ see:
+ FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLpoints">-</a>
+
+ FORALLpoints { ... }
+ assign 'point' to each point in qh.first_point, qh.num_points
+
+ declare:
+ coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLpoint_">-</a>
+
+ FORALLpoint_( points, num) { ... }
+ assign 'point' to each point in points array of num points
+
+ declare:
+ coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(points, num) for(point= (points), \
+ pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FORALLvertices">-</a>
+
+ FORALLvertices { ... }
+ assign 'vertex' to each vertex in qh.vertex_list
+
+ declare:
+ vertexT *vertex;
+
+ notes:
+ assumes qh.vertex_list terminated with a sentinel
+*/
+#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHfacet_">-</a>
+
+ FOREACHfacet_( facets ) { ... }
+ assign 'facet' to each facet in facets
+
+ declare:
+ facetT *facet, **facetp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighbor_">-</a>
+
+ FOREACHneighbor_( facet ) { ... }
+ assign 'neighbor' to each neighbor in facet->neighbors
+
+ FOREACHneighbor_( vertex ) { ... }
+ assign 'neighbor' to each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighbor, **neighborp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighbor_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHpoint_">-</a>
+
+ FOREACHpoint_( points ) { ... }
+ assign 'point' to each point in points set
+
+ declare:
+ pointT *point, **pointp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHpoint_(points) FOREACHsetelement_(pointT, points, point)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHridge_">-</a>
+
+ FOREACHridge_( ridges ) { ... }
+ assign 'ridge' to each ridge in ridges set
+
+ declare:
+ ridgeT *ridge, **ridgep;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHridge_(ridges) FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertex_">-</a>
+
+ FOREACHvertex_( vertices ) { ... }
+ assign 'vertex' to each vertex in vertices set
+
+ declare:
+ vertexT *vertex, **vertexp;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHfacet_i_">-</a>
+
+ FOREACHfacet_i_( facets ) { ... }
+ assign 'facet' and 'facet_i' for each facet in facets set
+
+ declare:
+ facetT *facet;
+ int facet_n, facet_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHfacet_i_(facets) FOREACHsetelement_i_(facetT, facets, facet)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHneighbor_i_">-</a>
+
+ FOREACHneighbor_i_( facet ) { ... }
+ assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+ FOREACHneighbor_i_( vertex ) { ... }
+ assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
+
+ declare:
+ facetT *neighbor;
+ int neighbor_n, neighbor_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHneighbor_i_(facet) FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHpoint_i_">-</a>
+
+ FOREACHpoint_i_( points ) { ... }
+ assign 'point' and 'point_i' for each point in points set
+
+ declare:
+ pointT *point;
+ int point_n, point_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHpoint_i_(points) FOREACHsetelement_i_(pointT, points, point)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHridge_i_">-</a>
+
+ FOREACHridge_i_( ridges ) { ... }
+ assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+ declare:
+ ridgeT *ridge;
+ int ridge_n, ridge_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHridge_i_(ridges) FOREACHsetelement_i_(ridgeT, ridges, ridge)
+
+/*-<a href="qh-poly.htm#TOC"
+ >--------------------------------</a><a name="FOREACHvertex_i_">-</a>
+
+ FOREACHvertex_i_( vertices ) { ... }
+ assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+ declare:
+ vertexT *vertex;
+ int vertex_n, vertex_i;
+
+ see:
+ <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+ */
+#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
+
+/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
+
+void qh_qhull (void);
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void qh_printsummary(FILE *fp);
+
+/********* -user.c prototypes (alphabetical) **********************/
+
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
+void qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
+ char *qhull_cmd, FILE *outfile, FILE *errfile);
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
+void qh_user_memsizes (void);
+
+/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
+
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+ boolT bestoutside, boolT newfacets, boolT noupper,
+ realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+ realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT qh_gram_schmidt(int dim, realT **rows);
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+void qh_printsummary(FILE *fp);
+void qh_projectinput (void);
+void qh_randommatrix (realT *buffer, int dim, realT **row);
+void qh_rotateinput (realT **rows);
+void qh_scaleinput (void);
+void qh_setdelaunay (int dim, int count, pointT *points);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock (void);
+void qh_checkflags (char *command, char *hiddenflags);
+void qh_freebuffers (void);
+void qh_freeqhull (boolT allmem);
+void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_init_qhull_command (int argc, char *argv[]);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_initflags (char *command);
+void qh_initqhull_buffers (void);
+void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
+void qh_initqhull_mem (void);
+void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
+void qh_initthresholds (char *command);
+void qh_option (char *option, int *i, realT *r);
+#if qh_QHpointer
+void qh_restore_qhull (qhT **oldqh);
+qhT *qh_save_qhull (void);
+#endif
+
+/***** -io.c prototypes (duplicated from io.h) ***********************/
+
+void dfacet( unsigned id);
+void dvertex( unsigned id);
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void qh_produce_output(void);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -mem.c prototypes (duplicated from mem.h) **********************/
+
+void qh_meminit (FILE *ferr);
+void qh_memfreeshort (int *curlong, int *totlong);
+
+/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
+
+void qh_check_output (void);
+void qh_check_points (void);
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+ realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point (int id);
+setT *qh_pointfacet (void /*qh.facet_list*/);
+int qh_pointid (pointT *point);
+setT *qh_pointvertex (void /*qh.facet_list*/);
+void qh_setvoronoi_all (void);
+void qh_triangulate (void /*qh facet_list*/);
+
+/********* -stat.c prototypes (duplicated from stat.h) **********************/
+
+void qh_collectstatistics (void);
+void qh_printallstatistics (FILE *fp, char *string);
+
+#endif /* qhDEFqhull */
diff --git a/extern/qhull/src/qhull_a.h b/extern/qhull/src/qhull_a.h
new file mode 100644
index 00000000000..d4e69b071be
--- /dev/null
+++ b/extern/qhull/src/qhull_a.h
@@ -0,0 +1,127 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qhull_a.h
+ all header files for compiling qhull
+
+ see qh-qhull.htm
+
+ see qhull.h for user-level definitions
+
+ see user.h for user-defineable constants
+
+ defines internal functions for qhull.c global.c
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ Notes: grep for ((" and (" to catch fprintf("lkasdjf");
+ full parens around (x?y:z)
+ use '#include qhull/qhull_a.h' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+#include <math.h>
+#include <float.h> /* some compilers will not need float.h */
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+/*** uncomment here and qset.c
+ if string.h does not define memcpy()
+#include <memory.h>
+*/
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+#include "geom.h"
+#include "merge.h"
+#include "poly.h"
+#include "io.h"
+#include "stat.h"
+
+#if qh_CLOCKtype == 2 /* defined in user.h from qhull.h */
+#include <sys/types.h>
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+
+#ifdef _MSC_VER /* Microsoft Visual C++ */
+#pragma warning( disable : 4056) /* float constant expression. Looks like a compiler bug */
+#pragma warning( disable : 4146) /* unary minus applied to unsigned type */
+#pragma warning( disable : 4244) /* conversion from 'unsigned long' to 'real' */
+#pragma warning( disable : 4305) /* conversion from 'const double' to 'float' */
+#endif
+
+/* ======= -macros- =========== */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >--------------------------------</a><a name="traceN">-</a>
+
+ traceN((fp.ferr, "format\n", vars));
+ calls fprintf if qh.IStracing >= N
+
+ notes:
+ removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh IStracing) fprintf args;}
+#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
+#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
+#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
+#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
+#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/***** -qhull.c prototypes (alphabetical after qhull) ********************/
+
+void qh_qhull (void);
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void qh_buildhull(void);
+void qh_buildtracing (pointT *furthest, facetT *facet);
+void qh_build_withrestart (void);
+void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
+void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest (facetT **visible);
+void qh_partitionall(setT *vertices, pointT *points,int npoints);
+void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
+void qh_partitionpoint (pointT *point, facetT *facet);
+void qh_partitionvisible(boolT allpoints, int *numpoints);
+void qh_precision (char *reason);
+void qh_printsummary(FILE *fp);
+
+/***** -global.c internal prototypes (alphabetical) ***********************/
+
+void qh_appendprint (qh_PRINT format);
+void qh_freebuild (boolT allmem);
+void qh_freebuffers (void);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+int qh_strtol (const char *s, char **endp);
+double qh_strtod (const char *s, char **endp);
+
+/***** -stat.c internal prototypes (alphabetical) ***********************/
+
+void qh_allstatA (void);
+void qh_allstatB (void);
+void qh_allstatC (void);
+void qh_allstatD (void);
+void qh_allstatE (void);
+void qh_allstatE2 (void);
+void qh_allstatF (void);
+void qh_allstatG (void);
+void qh_allstatH (void);
+void qh_freebuffers (void);
+void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#endif /* qhDEFqhulla */
diff --git a/extern/qhull/src/qhull_interface.cpp b/extern/qhull/src/qhull_interface.cpp
new file mode 100644
index 00000000000..6ecc640e82b
--- /dev/null
+++ b/extern/qhull/src/qhull_interface.cpp
@@ -0,0 +1,96 @@
+/*<html><pre> -<a href="qh-user.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+*/
+
+#include <iostream.h>
+#include <conio.h>
+
+//--- Include qhull, so it works from with in a C++ source file
+//---
+//--- In MVC one cannot just do:
+//---
+//--- extern "C"
+//--- {
+//--- #include "qhull_a.h"
+//--- }
+//---
+//--- Because qhull_a.h includes math.h, which can not appear
+//--- inside a extern "C" declaration.
+//---
+//--- Maybe that why Numerical recipes in C avoid this problem, by removing
+//--- standard include headers from its header files and add them in the
+//--- respective source files instead.
+//---
+//--- [K. Erleben]
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <qhull/qhull.h>
+#include <qhull/mem.h>
+#include <qhull/qset.h>
+#include <qhull/geom.h>
+#include <qhull/merge.h>
+#include <qhull/poly.h>
+#include <qhull/io.h>
+#include <qhull/stat.h>
+#if defined(__cplusplus)
+}
+#endif
+
+/*********************************************************************/
+/* */
+/* */
+/* */
+/* */
+/*********************************************************************/
+
+void compute_convex_hull(void)
+{
+ int dim; /* dimension of points */
+ int numpoints; /* number of points */
+ coordT *points; /* array of coordinates for each point */
+ boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
+ char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
+ FILE *outfile= stdout; /* output from qh_produce_output()
+ use NULL to skip qh_produce_output() */
+ FILE *errfile= stderr; /* error messages from qhull code */
+ int exitcode; /* 0 if no error from qhull */
+ facetT *facet; /* set by FORALLfacets */
+ int curlong, totlong; /* memory remaining after qh_memfreeshort */
+
+ /* initialize dim, numpoints, points[], ismalloc here */
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode) { /* if no error */
+ /* 'qh facet_list' contains the convex hull */
+ FORALLfacets {
+ /* ... your code ... */
+ }
+ }
+ qh_freeqhull(!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+};
+
+/*********************************************************************/
+/* */
+/* */
+/* */
+/* */
+/*********************************************************************/
+
+void main()
+{
+ cout << "Hello world" << endl;
+
+ cout << "Press any key..." << endl;
+
+ while(!_kbhit());
+
+};
diff --git a/extern/qhull/src/qset.c b/extern/qhull/src/qset.c
new file mode 100644
index 00000000000..9e78464c07e
--- /dev/null
+++ b/extern/qhull/src/qset.c
@@ -0,0 +1,1301 @@
+/*<html><pre> -<a href="qh-set.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qset.c
+ implements set manipulations needed for quickhull
+
+ see qh-set.htm and qset.h
+
+ copyright (c) 1993-2002 The Geometry Center
+*/
+
+#include <stdio.h>
+#include <string.h>
+/*** uncomment here and qhull_a.h
+ if string.h does not define memcpy()
+#include <memory.h>
+*/
+#include "qset.h"
+#include "mem.h"
+
+#ifndef qhDEFqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void qh_errexit(int exitcode, facetT *, ridgeT *);
+#endif
+
+/*=============== internal macros ===========================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="SETsizeaddr_">-</a>
+
+ SETsizeaddr_(set)
+ return pointer to actual size+1 of set (set CANNOT be NULL!!)
+
+ notes:
+ *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
+*/
+#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize].i))
+
+/*============ functions in alphabetical order ===================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >--------------------------------<a name="setaddnth">-</a>
+
+ qh_setaddnth( setp, nth, newelem)
+ adds newelem as n'th element of sorted or unsorted *setp
+
+ notes:
+ *setp and newelem must be defined
+ *setp may be a temp set
+ nth=0 is first element
+ errors if nth is out of bounds
+
+ design:
+ expand *setp if empty or full
+ move tail of *setp up one
+ insert newelem
+*/
+void qh_setaddnth(setT **setp, int nth, void *newelem) {
+ int *sizep, oldsize, i;
+ void **oldp, **newp;
+
+ if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+ qh_setlarger(setp);
+ sizep= SETsizeaddr_(*setp);
+ }
+ oldsize= *sizep - 1;
+ if (nth < 0 || nth > oldsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+ qh_setprint (qhmem.ferr, "", *setp);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ (*sizep)++;
+ oldp= SETelemaddr_(*setp, oldsize, void); /* NULL */
+ newp= oldp+1;
+ for (i= oldsize-nth+1; i--; ) /* move at least NULL */
+ *(newp--)= *(oldp--); /* may overwrite *sizep */
+ *newp= newelem;
+} /* setaddnth */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >--------------------------------<a name="setaddsorted">-</a>
+
+ setaddsorted( setp, newelem )
+ adds an newelem into sorted *setp
+
+ notes:
+ *setp and newelem must be defined
+ *setp may be a temp set
+ nop if newelem already in set
+
+ design:
+ find newelem's position in *setp
+ insert newelem
+*/
+void qh_setaddsorted(setT **setp, void *newelem) {
+ int newindex=0;
+ void *elem, **elemp;
+
+ FOREACHelem_(*setp) { /* could use binary search instead */
+ if (elem < newelem)
+ newindex++;
+ else if (elem == newelem)
+ return;
+ else
+ break;
+ }
+ qh_setaddnth(setp, newindex, newelem);
+} /* setaddsorted */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setappend">-</a>
+
+ qh_setappend( setp, newelem)
+ append newelem to *setp
+
+ notes:
+ *setp may be a temp set
+ *setp and newelem may be NULL
+
+ design:
+ expand *setp if empty or full
+ append newelem to *setp
+
+*/
+void qh_setappend(setT **setp, void *newelem) {
+ int *sizep;
+ void **endp;
+
+ if (!newelem)
+ return;
+ if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+ qh_setlarger(setp);
+ sizep= SETsizeaddr_(*setp);
+ }
+ *(endp= &((*setp)->e[(*sizep)++ - 1].p))= newelem;
+ *(++endp)= NULL;
+} /* setappend */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setappend_set">-</a>
+
+ qh_setappend_set( setp, setA)
+ appends setA to *setp
+
+ notes:
+ *setp can not be a temp set
+ *setp and setA may be NULL
+
+ design:
+ setup for copy
+ expand *setp if it is too small
+ append all elements of setA to *setp
+*/
+void qh_setappend_set(setT **setp, setT *setA) {
+ int *sizep, sizeA, size;
+ setT *oldset;
+
+ if (!setA)
+ return;
+ SETreturnsize_(setA, sizeA);
+ if (!*setp)
+ *setp= qh_setnew (sizeA);
+ sizep= SETsizeaddr_(*setp);
+ if (!(size= *sizep))
+ size= (*setp)->maxsize;
+ else
+ size--;
+ if (size + sizeA > (*setp)->maxsize) {
+ oldset= *setp;
+ *setp= qh_setcopy (oldset, sizeA);
+ qh_setfree (&oldset);
+ sizep= SETsizeaddr_(*setp);
+ }
+ *sizep= size+sizeA+1; /* memcpy may overwrite */
+ if (sizeA > 0)
+ memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), SETelemsize *(sizeA+1));
+} /* setappend_set */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setappend2ndlast">-</a>
+
+ qh_setappend2ndlast( setp, newelem )
+ makes newelem the next to the last element in *setp
+
+ notes:
+ *setp must have at least one element
+ newelem must be defined
+ *setp may be a temp set
+
+ design:
+ expand *setp if empty or full
+ move last element of *setp up one
+ insert newelem
+*/
+void qh_setappend2ndlast(setT **setp, void *newelem) {
+ int *sizep;
+ void **endp, **lastp;
+
+ if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+ qh_setlarger(setp);
+ sizep= SETsizeaddr_(*setp);
+ }
+ endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */
+ lastp= endp-1;
+ *(endp++)= *lastp;
+ *endp= NULL; /* may overwrite *sizep */
+ *lastp= newelem;
+} /* setappend2ndlast */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setcheck">-</a>
+
+ qh_setcheck( set, typename, id )
+ check set for validity
+ report errors with typename and id
+
+ design:
+ checks that maxsize, actual size, and NULL terminator agree
+*/
+void qh_setcheck(setT *set, char *tname, int id) {
+ int maxsize, size;
+ int waserr= 0;
+
+ if (!set)
+ return;
+ SETreturnsize_(set, size);
+ maxsize= set->maxsize;
+ if (size > maxsize || !maxsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
+ size, tname, id, maxsize);
+ waserr= 1;
+ }else if (set->e[size].p) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): %s%d (size %d max %d) is not null terminated.\n",
+ tname, id, maxsize, size-1);
+ waserr= 1;
+ }
+ if (waserr) {
+ qh_setprint (qhmem.ferr, "ERRONEOUS", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+} /* setcheck */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setcompact">-</a>
+
+ qh_setcompact( set )
+ remove internal NULLs from an unsorted set
+
+ returns:
+ updated set
+
+ notes:
+ set may be NULL
+ it would be faster to swap tail of set into holes, like qh_setdel
+
+ design:
+ setup pointers into set
+ skip NULLs while copying elements to start of set
+ update the actual size
+*/
+void qh_setcompact(setT *set) {
+ int size;
+ void **destp, **elemp, **endp, **firstp;
+
+ if (!set)
+ return;
+ SETreturnsize_(set, size);
+ destp= elemp= firstp= SETaddr_(set, void);
+ endp= destp + size;
+ while (1) {
+ if (!(*destp++ = *elemp++)) {
+ destp--;
+ if (elemp > endp)
+ break;
+ }
+ }
+ qh_settruncate (set, destp-firstp);
+} /* setcompact */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setcopy">-</a>
+
+ qh_setcopy( set, extra )
+ make a copy of a sorted or unsorted set with extra slots
+
+ returns:
+ new set
+
+ design:
+ create a newset with extra slots
+ copy the elements to the newset
+
+*/
+setT *qh_setcopy(setT *set, int extra) {
+ setT *newset;
+ int size;
+
+ if (extra < 0)
+ extra= 0;
+ SETreturnsize_(set, size);
+ newset= qh_setnew(size+extra);
+ *SETsizeaddr_(newset)= size+1; /* memcpy may overwrite */
+ memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), SETelemsize *(size+1));
+ return (newset);
+} /* setcopy */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setdel">-</a>
+
+ qh_setdel( set, oldelem )
+ delete oldelem from an unsorted set
+
+ returns:
+ returns oldelem if found
+ returns NULL otherwise
+
+ notes:
+ set may be NULL
+ oldelem must not be NULL;
+ only deletes one copy of oldelem in set
+
+ design:
+ locate oldelem
+ update actual size if it was full
+ move the last element to the oldelem's location
+*/
+void *qh_setdel(setT *set, void *oldelem) {
+ void **elemp, **lastp;
+ int *sizep;
+
+ if (!set)
+ return NULL;
+ elemp= SETaddr_(set, void);
+ while (*elemp != oldelem && *elemp)
+ elemp++;
+ if (*elemp) {
+ sizep= SETsizeaddr_(set);
+ if (!(*sizep)--) /* if was a full set */
+ *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
+ lastp= SETelemaddr_(set, *sizep-1, void);
+ *elemp= *lastp; /* may overwrite itself */
+ *lastp= NULL;
+ return oldelem;
+ }
+ return NULL;
+} /* setdel */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setdellast">-</a>
+
+ qh_setdellast( set)
+ return last element of set or NULL
+
+ notes:
+ deletes element from set
+ set may be NULL
+
+ design:
+ return NULL if empty
+ if full set
+ delete last element and set actual size
+ else
+ delete last element and update actual size
+*/
+void *qh_setdellast(setT *set) {
+ int setsize; /* actually, actual_size + 1 */
+ int maxsize;
+ int *sizep;
+ void *returnvalue;
+
+ if (!set || !(set->e[0].p))
+ return NULL;
+ sizep= SETsizeaddr_(set);
+ if ((setsize= *sizep)) {
+ returnvalue= set->e[setsize - 2].p;
+ set->e[setsize - 2].p= NULL;
+ (*sizep)--;
+ }else {
+ maxsize= set->maxsize;
+ returnvalue= set->e[maxsize - 1].p;
+ set->e[maxsize - 1].p= NULL;
+ *sizep= maxsize;
+ }
+ return returnvalue;
+} /* setdellast */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setdelnth">-</a>
+
+ qh_setdelnth( set, nth )
+ deletes nth element from unsorted set
+ 0 is first element
+
+ returns:
+ returns the element (needs type conversion)
+
+ notes:
+ errors if nth invalid
+
+ design:
+ setup points and check nth
+ delete nth element and overwrite with last element
+*/
+void *qh_setdelnth(setT *set, int nth) {
+ void **elemp, **lastp, *elem;
+ int *sizep;
+
+
+ elemp= SETelemaddr_(set, nth, void);
+ sizep= SETsizeaddr_(set);
+ if (!(*sizep)--) /* if was a full set */
+ *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
+ if (nth < 0 || nth >= *sizep) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ lastp= SETelemaddr_(set, *sizep-1, void);
+ elem= *elemp;
+ *elemp= *lastp; /* may overwrite itself */
+ *lastp= NULL;
+ return elem;
+} /* setdelnth */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setdelnthsorted">-</a>
+
+ qh_setdelnthsorted( set, nth )
+ deletes nth element from sorted set
+
+ returns:
+ returns the element (use type conversion)
+
+ notes:
+ errors if nth invalid
+
+ see also:
+ setnew_delnthsorted
+
+ design:
+ setup points and check nth
+ copy remaining elements down one
+ update actual size
+*/
+void *qh_setdelnthsorted(setT *set, int nth) {
+ void **newp, **oldp, *elem;
+ int *sizep;
+
+ sizep= SETsizeaddr_(set);
+ if (nth < 0 || (*sizep && nth >= *sizep-1) || nth >= set->maxsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ newp= SETelemaddr_(set, nth, void);
+ elem= *newp;
+ oldp= newp+1;
+ while ((*(newp++)= *(oldp++)))
+ ; /* copy remaining elements and NULL */
+ if (!(*sizep)--) /* if was a full set */
+ *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */
+ return elem;
+} /* setdelnthsorted */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setdelsorted">-</a>
+
+ qh_setdelsorted( set, oldelem )
+ deletes oldelem from sorted set
+
+ returns:
+ returns oldelem if it was deleted
+
+ notes:
+ set may be NULL
+
+ design:
+ locate oldelem in set
+ copy remaining elements down one
+ update actual size
+*/
+void *qh_setdelsorted(setT *set, void *oldelem) {
+ void **newp, **oldp;
+ int *sizep;
+
+ if (!set)
+ return NULL;
+ newp= SETaddr_(set, void);
+ while(*newp != oldelem && *newp)
+ newp++;
+ if (*newp) {
+ oldp= newp+1;
+ while ((*(newp++)= *(oldp++)))
+ ; /* copy remaining elements */
+ sizep= SETsizeaddr_(set);
+ if (!(*sizep)--) /* if was a full set */
+ *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */
+ return oldelem;
+ }
+ return NULL;
+} /* setdelsorted */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setduplicate">-</a>
+
+ qh_setduplicate( set, elemsize )
+ duplicate a set of elemsize elements
+
+ notes:
+ use setcopy if retaining old elements
+
+ design:
+ create a new set
+ for each elem of the old set
+ create a newelem
+ append newelem to newset
+*/
+setT *qh_setduplicate (setT *set, int elemsize) {
+ void *elem, **elemp, *newElem;
+ setT *newSet;
+ int size;
+
+ if (!(size= qh_setsize (set)))
+ return NULL;
+ newSet= qh_setnew (size);
+ FOREACHelem_(set) {
+ newElem= qh_memalloc (elemsize);
+ memcpy (newElem, elem, elemsize);
+ qh_setappend (&newSet, newElem);
+ }
+ return newSet;
+} /* setduplicate */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setequal">-</a>
+
+ qh_setequal( )
+ returns 1 if two sorted sets are equal, otherwise returns 0
+
+ notes:
+ either set may be NULL
+
+ design:
+ check size of each set
+ setup pointers
+ compare elements of each set
+*/
+int qh_setequal(setT *setA, setT *setB) {
+ void **elemAp, **elemBp;
+ int sizeA, sizeB;
+
+ SETreturnsize_(setA, sizeA);
+ SETreturnsize_(setB, sizeB);
+ if (sizeA != sizeB)
+ return 0;
+ if (!sizeA)
+ return 1;
+ elemAp= SETaddr_(setA, void);
+ elemBp= SETaddr_(setB, void);
+ if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
+ return 1;
+ return 0;
+} /* setequal */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setequal_except">-</a>
+
+ qh_setequal_except( setA, skipelemA, setB, skipelemB )
+ returns 1 if sorted setA and setB are equal except for skipelemA & B
+
+ returns:
+ false if either skipelemA or skipelemB are missing
+
+ notes:
+ neither set may be NULL
+
+ if skipelemB is NULL,
+ can skip any one element of setB
+
+ design:
+ setup pointers
+ search for skipelemA, skipelemB, and mismatches
+ check results
+*/
+int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
+ void **elemA, **elemB;
+ int skip=0;
+
+ elemA= SETaddr_(setA, void);
+ elemB= SETaddr_(setB, void);
+ while (1) {
+ if (*elemA == skipelemA) {
+ skip++;
+ elemA++;
+ }
+ if (skipelemB) {
+ if (*elemB == skipelemB) {
+ skip++;
+ elemB++;
+ }
+ }else if (*elemA != *elemB) {
+ skip++;
+ if (!(skipelemB= *elemB++))
+ return 0;
+ }
+ if (!*elemA)
+ break;
+ if (*elemA++ != *elemB++)
+ return 0;
+ }
+ if (skip != 2 || *elemB)
+ return 0;
+ return 1;
+} /* setequal_except */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setequal_skip">-</a>
+
+ qh_setequal_skip( setA, skipA, setB, skipB )
+ returns 1 if sorted setA and setB are equal except for elements skipA & B
+
+ returns:
+ false if different size
+
+ notes:
+ neither set may be NULL
+
+ design:
+ setup pointers
+ search for mismatches while skipping skipA and skipB
+*/
+int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) {
+ void **elemA, **elemB, **skipAp, **skipBp;
+
+ elemA= SETaddr_(setA, void);
+ elemB= SETaddr_(setB, void);
+ skipAp= SETelemaddr_(setA, skipA, void);
+ skipBp= SETelemaddr_(setB, skipB, void);
+ while (1) {
+ if (elemA == skipAp)
+ elemA++;
+ if (elemB == skipBp)
+ elemB++;
+ if (!*elemA)
+ break;
+ if (*elemA++ != *elemB++)
+ return 0;
+ }
+ if (*elemB)
+ return 0;
+ return 1;
+} /* setequal_skip */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setfree">-</a>
+
+ qh_setfree( setp )
+ frees the space occupied by a sorted or unsorted set
+
+ returns:
+ sets setp to NULL
+
+ notes:
+ set may be NULL
+
+ design:
+ free array
+ free set
+*/
+void qh_setfree(setT **setp) {
+ int size;
+ void **freelistp; /* used !qh_NOmem */
+
+ if (*setp) {
+ size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
+ if (size <= qhmem.LASTsize) {
+ qh_memfree_(*setp, size, freelistp);
+ }else
+ qh_memfree (*setp, size);
+ *setp= NULL;
+ }
+} /* setfree */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setfree2">-</a>
+
+ qh_setfree2( setp, elemsize )
+ frees the space occupied by a set and its elements
+
+ notes:
+ set may be NULL
+
+ design:
+ free each element
+ free set
+*/
+void qh_setfree2 (setT **setp, int elemsize) {
+ void *elem, **elemp;
+
+ FOREACHelem_(*setp)
+ qh_memfree (elem, elemsize);
+ qh_setfree (setp);
+} /* setfree2 */
+
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setfreelong">-</a>
+
+ qh_setfreelong( setp )
+ frees a set only if it's in long memory
+
+ returns:
+ sets setp to NULL if it is freed
+
+ notes:
+ set may be NULL
+
+ design:
+ if set is large
+ free it
+*/
+void qh_setfreelong(setT **setp) {
+ int size;
+
+ if (*setp) {
+ size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
+ if (size > qhmem.LASTsize) {
+ qh_memfree (*setp, size);
+ *setp= NULL;
+ }
+ }
+} /* setfreelong */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setin">-</a>
+
+ qh_setin( set, setelem )
+ returns 1 if setelem is in a set, 0 otherwise
+
+ notes:
+ set may be NULL or unsorted
+
+ design:
+ scans set for setelem
+*/
+int qh_setin(setT *set, void *setelem) {
+ void *elem, **elemp;
+
+ FOREACHelem_(set) {
+ if (elem == setelem)
+ return 1;
+ }
+ return 0;
+} /* setin */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setindex">-</a>
+
+ qh_setindex( set, atelem )
+ returns the index of atelem in set.
+ returns -1, if not in set or maxsize wrong
+
+ notes:
+ set may be NULL and may contain nulls.
+
+ design:
+ checks maxsize
+ scans set for atelem
+*/
+int qh_setindex(setT *set, void *atelem) {
+ void **elem;
+ int size, i;
+
+ SETreturnsize_(set, size);
+ if (size > set->maxsize)
+ return -1;
+ elem= SETaddr_(set, void);
+ for (i=0; i < size; i++) {
+ if (*elem++ == atelem)
+ return i;
+ }
+ return -1;
+} /* setindex */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setlarger">-</a>
+
+ qh_setlarger( oldsetp )
+ returns a larger set that contains all elements of *oldsetp
+
+ notes:
+ the set is at least twice as large
+ if temp set, updates qhmem.tempstack
+
+ design:
+ creates a new set
+ copies the old set to the new set
+ updates pointers in tempstack
+ deletes the old set
+*/
+void qh_setlarger(setT **oldsetp) {
+ int size= 1, *sizep;
+ setT *newset, *set, **setp, *oldset;
+ void **oldp, **newp;
+
+ if (*oldsetp) {
+ oldset= *oldsetp;
+ SETreturnsize_(oldset, size);
+ qhmem.cntlarger++;
+ qhmem.totlarger += size+1;
+ newset= qh_setnew(2 * size);
+ oldp= SETaddr_(oldset, void);
+ newp= SETaddr_(newset, void);
+ memcpy((char *)newp, (char *)oldp, (size+1) * SETelemsize);
+ sizep= SETsizeaddr_(newset);
+ *sizep= size+1;
+ FOREACHset_((setT *)qhmem.tempstack) {
+ if (set == oldset)
+ *(setp-1)= newset;
+ }
+ qh_setfree(oldsetp);
+ }else
+ newset= qh_setnew(3);
+ *oldsetp= newset;
+} /* setlarger */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setlast">-</a>
+
+ qh_setlast( )
+ return last element of set or NULL (use type conversion)
+
+ notes:
+ set may be NULL
+
+ design:
+ return last element
+*/
+void *qh_setlast(setT *set) {
+ int size;
+
+ if (set) {
+ size= *SETsizeaddr_(set);
+ if (!size)
+ return SETelem_(set, set->maxsize - 1);
+ else if (size > 1)
+ return SETelem_(set, size - 2);
+ }
+ return NULL;
+} /* setlast */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setnew">-</a>
+
+ qh_setnew( setsize )
+ creates and allocates space for a set
+
+ notes:
+ setsize means the number of elements (NOT including the NULL terminator)
+ use qh_settemp/qh_setfreetemp if set is temporary
+
+ design:
+ allocate memory for set
+ roundup memory if small set
+ initialize as empty set
+*/
+setT *qh_setnew(int setsize) {
+ setT *set;
+ int sizereceived; /* used !qh_NOmem */
+ int size;
+ void **freelistp; /* used !qh_NOmem */
+
+ if (!setsize)
+ setsize++;
+ size= sizeof(setT) + setsize * SETelemsize;
+ if ((unsigned) size <= (unsigned) qhmem.LASTsize) {
+ qh_memalloc_(size, freelistp, set, setT);
+#ifndef qh_NOmem
+ sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
+ if (sizereceived > size)
+ setsize += (sizereceived - size)/SETelemsize;
+#endif
+ }else
+ set= (setT*)qh_memalloc (size);
+ set->maxsize= setsize;
+ set->e[setsize].i= 1;
+ set->e[0].p= NULL;
+ return (set);
+} /* setnew */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setnew_delnthsorted">-</a>
+
+ qh_setnew_delnthsorted( set, size, nth, prepend )
+ creates a sorted set not containing nth element
+ if prepend, the first prepend elements are undefined
+
+ notes:
+ set must be defined
+ checks nth
+ see also: setdelnthsorted
+
+ design:
+ create new set
+ setup pointers and allocate room for prepend'ed entries
+ append head of old set to new set
+ append tail of old set to new set
+*/
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
+ setT *newset;
+ void **oldp, **newp;
+ int tailsize= size - nth -1, newsize;
+
+ if (tailsize < 0) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ newsize= size-1 + prepend;
+ newset= qh_setnew(newsize);
+ newset->e[newset->maxsize].i= newsize+1; /* may be overwritten */
+ oldp= SETaddr_(set, void);
+ newp= SETaddr_(newset, void) + prepend;
+ switch (nth) {
+ case 0:
+ break;
+ case 1:
+ *(newp++)= *oldp++;
+ break;
+ case 2:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ case 3:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ case 4:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ default:
+ memcpy((char *)newp, (char *)oldp, nth * SETelemsize);
+ newp += nth;
+ oldp += nth;
+ break;
+ }
+ oldp++;
+ switch (tailsize) {
+ case 0:
+ break;
+ case 1:
+ *(newp++)= *oldp++;
+ break;
+ case 2:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ case 3:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ case 4:
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ *(newp++)= *oldp++;
+ break;
+ default:
+ memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize);
+ newp += tailsize;
+ }
+ *newp= NULL;
+ return(newset);
+} /* setnew_delnthsorted */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setprint">-</a>
+
+ qh_setprint( fp, string, set )
+ print set elements to fp with identifying string
+
+ notes:
+ never errors
+*/
+void qh_setprint(FILE *fp, char* string, setT *set) {
+ int size, k;
+
+ if (!set)
+ fprintf (fp, "%s set is null\n", string);
+ else {
+ SETreturnsize_(set, size);
+ fprintf (fp, "%s set=%p maxsize=%d size=%d elems=",
+ string, set, set->maxsize, size);
+ if (size > set->maxsize)
+ size= set->maxsize+1;
+ for (k=0; k < size; k++)
+ fprintf(fp, " %p", set->e[k].p);
+ fprintf(fp, "\n");
+ }
+} /* setprint */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setreplace">-</a>
+
+ qh_setreplace( set, oldelem, newelem )
+ replaces oldelem in set with newelem
+
+ notes:
+ errors if oldelem not in the set
+ newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
+
+ design:
+ find oldelem
+ replace with newelem
+*/
+void qh_setreplace(setT *set, void *oldelem, void *newelem) {
+ void **elemp;
+
+ elemp= SETaddr_(set, void);
+ while(*elemp != oldelem && *elemp)
+ elemp++;
+ if (*elemp)
+ *elemp= newelem;
+ else {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setreplace): elem %p not found in set\n",
+ oldelem);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+} /* setreplace */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setsize">-</a>
+
+ qh_setsize( set )
+ returns the size of a set
+
+ notes:
+ errors if set's maxsize is incorrect
+ same as SETreturnsize_(set)
+
+ design:
+ determine actual size of set from maxsize
+*/
+int qh_setsize(setT *set) {
+ int size, *sizep;
+
+ if (!set)
+ return (0);
+ sizep= SETsizeaddr_(set);
+ if ((size= *sizep)) {
+ size--;
+ if (size > set->maxsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
+ size, set->maxsize);
+ qh_setprint (qhmem.ferr, "set: ", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ }else
+ size= set->maxsize;
+ return size;
+} /* setsize */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settemp">-</a>
+
+ qh_settemp( setsize )
+ return a stacked, temporary set of upto setsize elements
+
+ notes:
+ use settempfree or settempfree_all to release from qhmem.tempstack
+ see also qh_setnew
+
+ design:
+ allocate set
+ append to qhmem.tempstack
+
+*/
+setT *qh_settemp(int setsize) {
+ setT *newset;
+
+ newset= qh_setnew (setsize);
+ qh_setappend ((setT **)&qhmem.tempstack, newset);
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n",
+ newset, newset->maxsize, qh_setsize ((setT*)qhmem.tempstack));
+ return newset;
+} /* settemp */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settempfree">-</a>
+
+ qh_settempfree( set )
+ free temporary set at top of qhmem.tempstack
+
+ notes:
+ nop if set is NULL
+ errors if set not from previous qh_settemp
+
+ to locate errors:
+ use 'T2' to find source and then find mis-matching qh_settemp
+
+ design:
+ check top of qhmem.tempstack
+ free it
+*/
+void qh_settempfree(setT **set) {
+ setT *stackedset;
+
+ if (!*set)
+ return;
+ stackedset= qh_settemppop ();
+ if (stackedset != *set) {
+ qh_settemppush(stackedset);
+ fprintf (qhmem.ferr, "qhull internal error (qh_settempfree): set %p (size %d) was not last temporary allocated (depth %d, set %p, size %d)\n",
+ *set, qh_setsize(*set), qh_setsize((setT*)qhmem.tempstack)+1,
+ stackedset, qh_setsize(stackedset));
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ qh_setfree (set);
+} /* settempfree */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settempfree_all">-</a>
+
+ qh_settempfree_all( )
+ free all temporary sets in qhmem.tempstack
+
+ design:
+ for each set in tempstack
+ free set
+ free qhmem.tempstack
+*/
+void qh_settempfree_all(void) {
+ setT *set, **setp;
+
+ FOREACHset_((setT *)qhmem.tempstack)
+ qh_setfree(&set);
+ qh_setfree((setT **)&qhmem.tempstack);
+} /* settempfree_all */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settemppop">-</a>
+
+ qh_settemppop( )
+ pop and return temporary set from qhmem.tempstack
+
+ notes:
+ the returned set is permanent
+
+ design:
+ pop and check top of qhmem.tempstack
+*/
+setT *qh_settemppop(void) {
+ setT *stackedset;
+
+ stackedset= (setT*)qh_setdellast((setT *)qhmem.tempstack);
+ if (!stackedset) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n",
+ qh_setsize((setT*)qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
+ return stackedset;
+} /* settemppop */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settemppush">-</a>
+
+ qh_settemppush( set )
+ push temporary set unto qhmem.tempstack (makes it temporary)
+
+ notes:
+ duplicates settemp() for tracing
+
+ design:
+ append set to tempstack
+*/
+void qh_settemppush(setT *set) {
+
+ qh_setappend ((setT**)&qhmem.tempstack, set);
+ if (qhmem.IStracing >= 5)
+ fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n",
+ qh_setsize((setT*)qhmem.tempstack), set, qh_setsize(set));
+} /* settemppush */
+
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="settruncate">-</a>
+
+ qh_settruncate( set, size )
+ truncate set to size elements
+
+ notes:
+ set must be defined
+
+ see:
+ SETtruncate_
+
+ design:
+ check size
+ update actual size of set
+*/
+void qh_settruncate (setT *set, int size) {
+
+ if (size < 0 || size > set->maxsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ set->e[set->maxsize].i= size+1; /* maybe overwritten */
+ set->e[size].p= NULL;
+} /* settruncate */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setunique">-</a>
+
+ qh_setunique( set, elem )
+ add elem to unsorted set unless it is already in set
+
+ notes:
+ returns 1 if it is appended
+
+ design:
+ if elem not in set
+ append elem to set
+*/
+int qh_setunique (setT **set, void *elem) {
+
+ if (!qh_setin (*set, elem)) {
+ qh_setappend (set, elem);
+ return 1;
+ }
+ return 0;
+} /* setunique */
+
+/*-<a href="qh-set.htm#TOC"
+ >-------------------------------<a name="setzero">-</a>
+
+ qh_setzero( set, index, size )
+ zero elements from index on
+ set actual size of set to size
+
+ notes:
+ set must be defined
+ the set becomes an indexed set (can not use FOREACH...)
+
+ see also:
+ qh_settruncate
+
+ design:
+ check index and size
+ update actual size
+ zero elements starting at e[index]
+*/
+void qh_setzero (setT *set, int index, int size) {
+ int count;
+
+ if (index < 0 || index >= size || size > set->maxsize) {
+ fprintf (qhmem.ferr, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", index, size);
+ qh_setprint (qhmem.ferr, "", set);
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+ }
+ set->e[set->maxsize].i= size+1; /* may be overwritten */
+ count= size - index + 1; /* +1 for NULL terminator */
+ memset ((char *)SETelemaddr_(set, index, void), 0, count * SETelemsize);
+} /* setzero */
+
+
diff --git a/extern/qhull/src/qset.h b/extern/qhull/src/qset.h
new file mode 100644
index 00000000000..6c0ff758de4
--- /dev/null
+++ b/extern/qhull/src/qset.h
@@ -0,0 +1,468 @@
+/*<html><pre> -<a href="qh-set.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qset.h
+ header file for qset.c that implements set
+
+ see qh-set.htm and qset.c
+
+ only uses mem.c, malloc/free
+
+ for error handling, writes message and calls
+ qh_errexit (qhmem_ERRqhull, NULL, NULL);
+
+ set operations satisfy the following properties:
+ - sets have a max size, the actual size (if different) is stored at the end
+ - every set is NULL terminated
+ - sets may be sorted or unsorted, the caller must distinguish this
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */
+#endif
+
+/*-<a href="qh-set.htm#TOC"
+>----------------------------------------</a><a name="setT">-</a>
+
+setT
+ a set or list of pointers with maximum size and actual size.
+
+variations:
+ unsorted, unique -- a list of unique pointers with NULL terminator
+ user guarantees uniqueness
+ sorted -- a sorted list of unique pointers with NULL terminator
+ qset.c guarantees uniqueness
+ unsorted -- a list of pointers terminated with NULL
+ indexed -- an array of pointers with NULL elements
+
+structure for set of n elements:
+
+ --------------
+ | maxsize
+ --------------
+ | e[0] - a pointer, may be NULL for indexed sets
+ --------------
+ | e[1]
+
+ --------------
+ | ...
+ --------------
+ | e[n-1]
+ --------------
+ | e[n] = NULL
+ --------------
+ | ...
+ --------------
+ | e[maxsize] - n+1 or NULL (determines actual size of set)
+ --------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+ void *p;
+ int i; /* integer used for e[maxSize] */
+};
+
+struct setT {
+ int maxsize; /* maximum number of elements (except NULL) */
+ setelemT e[1]; /* array of pointers, tail is NULL */
+ /* last slot (unless NULL) is actual size+1
+ e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+ /* this may generate a warning since e[] contains
+ maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="SETelemsize">-</a>
+
+ SETelemsize
+ size of a set element in bytes
+*/
+#define SETelemsize sizeof(setelemT)
+
+
+/*=========== -macros- =========================*/
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHsetelement_">-</a>
+
+ FOREACHsetelement_(type, set, variable)
+ define FOREACH iterator
+
+ declare:
+ assumes *variable and **variablep are declared
+ no space in "variable)" [DEC Alpha cc compiler]
+
+ each iteration:
+ variable is set element
+ variablep is one beyond variable.
+
+ to repeat an element:
+ variablep--; / *repeat* /
+
+ at exit:
+ variable is NULL at end of loop
+
+ example:
+ #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
+
+ notes:
+ use FOREACHsetelement_i_() if need index or include NULLs
+
+ WARNING:
+ nested loops can't use the same variable (define another FOREACH)
+
+ needs braces if nested inside another FOREACH
+ this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##p= (type **)&((set)->e[0].p); \
+ (variable= *variable##p++);)
+
+/*-<a href="qh-set.htm#TOC"
+ >----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
+
+ FOREACHsetelement_i_(type, set, variable)
+ define indexed FOREACH iterator
+
+ declare:
+ type *variable, variable_n, variable_i;
+
+ each iteration:
+ variable is set element, may be NULL
+ variable_i is index, variable_n is qh_setsize()
+
+ to repeat an element:
+ variable_i--; variable_n-- repeats for deleted element
+
+ at exit:
+ variable==NULL and variable_i==variable_n
+
+ example:
+ #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
+
+ WARNING:
+ nested loops can't use the same variable (define another FOREACH)
+
+ needs braces if nested inside another FOREACH
+ this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(type, set, variable) \
+ if (((variable= NULL), set)) for (\
+ variable##_i= 0, variable= (type *)((set)->e[0].p), \
+ variable##_n= qh_setsize(set);\
+ variable##_i < variable##_n;\
+ variable= (type *)((set)->e[++variable##_i].p) )
+
+/*-<a href="qh-set.htm#TOC"
+ >--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
+
+ FOREACHsetelementreverse_(type, set, variable)-
+ define FOREACH iterator in reverse order
+
+ declare:
+ assumes *variable and **variablep are declared
+ also declare 'int variabletemp'
+
+ each iteration:
+ variable is set element
+
+ to repeat an element:
+ variabletemp++; / *repeat* /
+
+ at exit:
+ variable is NULL
+
+ example:
+ #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
+
+ notes:
+ use FOREACHsetelementreverse12_() to reverse first two elements
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
+ variable; variable= \
+ ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a>
+
+ FOREACHsetelementreverse12_(type, set, variable)-
+ define FOREACH iterator with e[1] and e[0] reversed
+
+ declare:
+ assumes *variable and **variablep are declared
+
+ each iteration:
+ variable is set element
+ variablep is one after variable.
+
+ to repeat an element:
+ variablep--; / *repeat* /
+
+ at exit:
+ variable is NULL at end of loop
+
+ example
+ #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+ if (((variable= NULL), set)) for(\
+ variable##p= (type **)&((set)->e[1].p); \
+ (variable= *variable##p); \
+ variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+ (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHelem_">-</a>
+
+ FOREACHelem_( set )-
+ iterate elements in a set
+
+ declare:
+ void *elem, *elemp;
+
+ each iteration:
+ elem is set element
+ elemp is one beyond
+
+ to repeat an element:
+ elemp--; / *repeat* /
+
+ at exit:
+ elem == NULL at end of loop
+
+ example:
+ FOREACHelem_(set) {
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------</a><a name="FOREACHset_">-</a>
+
+ FOREACHset_( set )-
+ iterate a set of sets
+
+ declare:
+ setT *set, **setp;
+
+ each iteration:
+ set is set element
+ setp is one beyond
+
+ to repeat an element:
+ setp--; / *repeat* /
+
+ at exit:
+ set == NULL at end of loop
+
+ example
+ FOREACHset_(sets) {
+
+ notes:
+ WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-<a href="qh-set.htm#TOC"
+ >-----------------------------------------</a><a name="SETindex_">-</a>
+
+ SETindex_( set, elem )
+ return index of elem in set
+
+ notes:
+ for use with FOREACH iteration
+
+ example:
+ i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETref_">-</a>
+
+ SETref_( elem )
+ l.h.s. for modifying the current element in a FOREACH iteration
+
+ example:
+ SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelem_">-</a>
+
+ SETelem_(set, n)
+ return the n'th element of set
+
+ notes:
+ assumes that n is valid [0..size] and that set is defined
+ use SETelemt_() for type cast
+*/
+#define SETelem_(set, n) ((set)->e[n].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelemt_">-</a>
+
+ SETelemt_(set, n, type)
+ return the n'th element of set as a type
+
+ notes:
+ assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type) ((type*)((set)->e[n].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETelemaddr_">-</a>
+
+ SETelemaddr_(set, n, type)
+ return address of the n'th element of a set
+
+ notes:
+ assumes that n is valid [0..size] and set is defined
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETfirst_">-</a>
+
+ SETfirst_(set)
+ return first element of set
+
+*/
+#define SETfirst_(set) ((set)->e[0].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETfirstt_">-</a>
+
+ SETfirstt_(set, type)
+ return first element of set as a type
+
+*/
+#define SETfirstt_(set, type) ((type*)((set)->e[0].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETsecond_">-</a>
+
+ SETsecond_(set)
+ return second element of set
+
+*/
+#define SETsecond_(set) ((set)->e[1].p)
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETsecondt_">-</a>
+
+ SETsecondt_(set, type)
+ return second element of set as a type
+*/
+#define SETsecondt_(set, type) ((type*)((set)->e[1].p))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETaddr_">-</a>
+
+ SETaddr_(set, type)
+ return address of set's elements
+*/
+#define SETaddr_(set,type) ((type **)(&((set)->e[0].p)))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETreturnsize_">-</a>
+
+ SETreturnsize_(set, size)
+ return size of a set
+
+ notes:
+ set must be defined
+ use qh_setsize(set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETempty_">-</a>
+
+ SETempty_(set)
+ return true (1) if set is empty
+
+ notes:
+ set may be NULL
+*/
+#define SETempty_(set) (!set || (SETfirst_(set) ? 0:1))
+
+/*-<a href="qh-set.htm#TOC"
+ >---------------------------------------</a><a name="SETtruncate_">-</a>
+
+ SETtruncate_(set)
+ return first element of set
+
+ see:
+ qh_settruncate()
+
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+ set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+void qh_setaddsorted(setT **setp, void *elem);
+void qh_setaddnth(setT **setp, int nth, void *newelem);
+void qh_setappend(setT **setp, void *elem);
+void qh_setappend_set(setT **setp, setT *setA);
+void qh_setappend2ndlast(setT **setp, void *elem);
+void qh_setcheck(setT *set, char *tname, int id);
+void qh_setcompact(setT *set);
+setT *qh_setcopy(setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(setT *set, int nth);
+void *qh_setdelnthsorted(setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate( setT *set, int elemsize);
+int qh_setequal(setT *setA, setT *setB);
+int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
+void qh_setfree(setT **set);
+void qh_setfree2( setT **setp, int elemsize);
+void qh_setfreelong(setT **set);
+int qh_setin(setT *set, void *setelem);
+int qh_setindex(setT *set, void *setelem);
+void qh_setlarger(setT **setp);
+void *qh_setlast(setT *set);
+setT *qh_setnew(int size);
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
+void qh_setprint(FILE *fp, char* string, setT *set);
+void qh_setreplace(setT *set, void *oldelem, void *newelem);
+int qh_setsize(setT *set);
+setT *qh_settemp(int setsize);
+void qh_settempfree(setT **set);
+void qh_settempfree_all(void);
+setT *qh_settemppop(void);
+void qh_settemppush(setT *set);
+void qh_settruncate (setT *set, int size);
+int qh_setunique (setT **set, void *elem);
+void qh_setzero (setT *set, int index, int size);
+
+
+#endif /* qhDEFset */
diff --git a/extern/qhull/src/qvoronoi.c b/extern/qhull/src/qvoronoi.c
new file mode 100644
index 00000000000..ebeb7367b87
--- /dev/null
+++ b/extern/qhull/src/qvoronoi.c
@@ -0,0 +1,318 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ qvoronoi.c
+ compute Voronoi diagrams and furthest-point Voronoi
+ diagrams using qhull
+
+ see unix.c for full interface
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+
+#elif __cplusplus
+extern "C" {
+ int isatty (int);
+}
+
+#elif _MSC_VER
+#include <io.h>
+#define isatty _isatty
+
+#else
+int isatty (int); /* returns 1 if stdin is a tty
+ if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*-<a href="qh-qhull.c#TOC"
+ >-------------------------------</a><a name="prompt">-</a>
+
+ qh_prompt
+ long prompt for qhull
+
+ notes:
+ restricted version of qhull.c
+
+ see:
+ concise prompt below
+*/
+
+/* duplicated in qvoron_f.htm and qvoronoi.htm */
+char hidden_options[]=" d n m v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V Fa FA FC Fp FS Ft FV Pv Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qvoronoi- compute the Voronoi diagram\n\
+ http://www.geom.umn.edu/software/qhull %s\n\
+\n\
+input (stdin):\n\
+ first lines: dimension and number of points (or vice-versa).\n\
+ other lines: point coordinates, best if one point per line\n\
+ comments: start with a non-numeric character\n\
+\n\
+options:\n\
+ Qu - compute furthest-site Voronoi diagram\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+\n\
+Qhull control options:\n\
+ Qz - add point-at-infinity to Voronoi diagram\n\
+ QJn - randomly joggle input in range [-n,n]\n\
+%s%s%s%s"; /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+ Qs - search all points for the initial simplex\n\
+ QGn - Voronoi vertices if visible from point n, -n if not\n\
+ QVn - Voronoi vertices for input point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+ T4 - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+ Tc - check frequently during execution\n\
+ Ts - statistics\n\
+ Tv - verify result: structure, convexity, and in-circle test\n\
+ Tz - send all output to stdout\n\
+ TFn - report summary when n or more facets created\n\
+ TI file - input data from file, no spaces or single quotes\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+ TPn - turn on tracing when point n added to hull\n\
+ TMn - turn on tracing at merge n\n\
+ TWn - trace merge facets when width > n\n\
+ TVn - stop qhull after adding point n, -n for before (see TCn)\n\
+ TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+ Cn - radius of centrum (roundoff added). Merge facets if non-convex\n\
+ An - cosine of maximum angle. Merge facets if cosine > n or non-convex\n\
+ C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+ Rn - randomly perturb computations by a factor of [1-n,1+n]\n\
+ Wn - min facet width for non-coincident point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+ s - summary to stderr\n\
+ p - Voronoi vertices\n\
+ o - OFF format (dim, Voronoi vertices, and Voronoi regions)\n\
+ i - Delaunay regions (use 'Pp' to avoid warning)\n\
+ f - facet dump\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+ Fc - count plus coincident points (by Voronoi vertex)\n\
+ Fd - use cdd format for input (homogeneous with offset first)\n\
+ FD - use cdd format for output (offset first)\n\
+ FF - facet dump without ridges\n\
+ Fi - separating hyperplanes for bounded Voronoi regions\n\
+ FI - ID for each Voronoi vertex\n\
+ Fm - merge count for each Voronoi vertex (511 max)\n\
+ Fn - count plus neighboring Voronoi vertices for each Voronoi vertex\n\
+ FN - count and Voronoi vertices for each Voronoi region\n\
+ Fo - separating hyperplanes for unbounded Voronoi regions\n\
+ FO - options and precision constants\n\
+ FP - nearest point and distance for each coincident point\n\
+ FQ - command used for qvoronoi\n\
+ Fs - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+ for output: #Voronoi regions, #Voronoi vertices,\n\
+ #coincident points, #non-simplicial regions\n\
+ #real (2), max outer plane and min vertex\n\
+ Fv - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
+ Fx - extreme points of Delaunay triangulation (on convex hull)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d only)\n\
+ Ga - all points as dots\n\
+ Gp - coplanar points and vertices as radii\n\
+ Gv - vertices as spheres\n\
+ Gi - inner planes only\n\
+ Gn - no planes\n\
+ Go - outer planes only\n\
+ Gc - centrums\n\
+ Gh - hyperplane intersections\n\
+ Gr - ridges\n\
+ GDn - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+ PAn - keep n largest Voronoi vertices by 'area'\n\
+ Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+ PDk:n - drop facet if normal[k] >= n\n\
+ Pg - print good Voronoi vertices (needs 'QGn' or 'QVn')\n\
+ PFn - keep Voronoi vertices whose 'area' is at least n\n\
+ PG - print neighbors of good Voronoi vertices\n\
+ PMn - keep n Voronoi vertices with most merges\n\
+ Po - force output. If error, output neighborhood of facet\n\
+ Pp - do not report precision problems\n\
+\n\
+ . - list of all options\n\
+ - - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt2">-</a>
+
+ qh_prompt2
+ synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qvoronoi- compute the Voronoi diagram. Qhull %s\n\
+ input (stdin): dimension, number of points, point coordinates\n\
+ comments start with a non-numeric character\n\
+\n\
+options (qvoronoi.htm):\n\
+ Qu - compute furthest-site Voronoi diagram\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Tv - verify result: structure, convexity, and in-circle test\n\
+ . - concise list of all options\n\
+ - - one-line description of all options\n\
+\n\
+output options (subset):\n\
+ s - summary of results (default)\n\
+ p - Voronoi vertices\n\
+ o - OFF file format (dim, Voronoi vertices, and Voronoi regions)\n\
+ FN - count and Voronoi vertices for each Voronoi region\n\
+ Fv - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
+ Fi - separating hyperplanes for bounded regions, 'Fo' for unbounded\n\
+ G - Geomview output (2-d only)\n\
+ QVn - Voronoi vertices for input point n, -n if not\n\
+ TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+rbox c P0 D2 | qvoronoi s o rbox c P0 D2 | qvoronoi Fi\n\
+rbox c P0 D2 | qvoronoi Fo rbox c P0 D2 | qvoronoi Fv\n\
+rbox c P0 D2 | qvoronoi s Qu Fv rbox c P0 D2 | qvoronoi Qu Fo\n\
+rbox c G1 d D2 | qvoronoi s p rbox c G1 d D2 | qvoronoi QJ s p\n\
+rbox c P0 D2 | qvoronoi s Fv QV0\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt3">-</a>
+
+ qh_prompt3
+ concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ OFF_format p_vertices i_delaunay summary facet_dump\n\
+\n\
+ Fcoincident Fd_cdd_in FD_cdd_out FF-dump-xridge Fi_bounded\n\
+ Fxtremes Fmerges Fneighbors FNeigh_region FOptions\n\
+ Fo_unbounded FPoint_near FQvoronoi Fsummary Fvoronoi\n\
+ FIDs\n\
+\n\
+ Gvertices Gpoints Gall_points Gno_planes Ginner\n\
+ Gcentrums Ghyperplanes Gridges Gouter GDrop_dim\n\
+\n\
+ PArea_keep Pdrop d0:0D0 Pgood PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep Poutput_forced Pprecision_not\n\
+\n\
+ QG_vertex_good QJoggle Qsearch_1st Qtriangulate Qupper_voronoi\n\
+ QV_point_good Qzinfinite\n\
+\n\
+ T4_trace Tcheck_often Tstatistics Tverify Tz_stdout\n\
+ TFacet_log TInput_file TPoint_trace TMerge_trace TOutput_file\n\
+ TWide_trace TVertex_stop TCone_stop\n\
+\n\
+ Angle_max Centrum_size Random_dist Wide_outside\n\
+";
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="main">-</a>
+
+ main( argc, argv )
+ processes the command line, calls qhull() to do the work, and exits
+
+ design:
+ initializes data structures
+ reads points
+ finishes initialization
+ computes convex hull and other structures
+ checks the result
+ writes the output
+ frees memory
+*/
+int main(int argc, char *argv[]) {
+ int curlong, totlong; /* used !qh_NOmem */
+ int exitcode, numpoints, dim;
+ coordT *points;
+ boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= false;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+
+ if ((argc == 1) && isatty( 0 /*stdin*/)) {
+ fprintf(stdout, qh_prompt2, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompta, qh_VERSION,
+ qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+ exit(qh_ERRnone);
+ }
+ if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompt3, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ qh_init_A (stdin, stdout, stderr, argc, argv); /* sets qh qhull_command */
+ exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+ if (!exitcode) {
+ qh_option ("voronoi _bbound-last _coplanar-keep", NULL, NULL);
+ qh DELAUNAY= True; /* 'v' */
+ qh VORONOI= True;
+ qh SCALElast= True; /* 'Qbb' */
+ qh_checkflags (qh qhull_command, hidden_options);
+ qh_initflags (qh qhull_command);
+ points= qh_readpoints (&numpoints, &dim, &ismalloc);
+ if (dim >= 5) {
+ qh_option ("_merge-exact", NULL, NULL);
+ qh MERGEexact= True; /* 'Qx' always */
+ }
+ qh_init_B (points, numpoints, dim, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ exitcode= qh_ERRnone;
+ }
+ qh NOerrexit= True; /* no more setjmp */
+#ifdef qh_NOmem
+ qh_freeqhull( True);
+#else
+ qh_freeqhull( False);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+#endif
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/rbox.c b/extern/qhull/src/rbox.c
new file mode 100644
index 00000000000..1c288bddc96
--- /dev/null
+++ b/extern/qhull/src/rbox.c
@@ -0,0 +1,788 @@
+/*<html><pre> -<a href="index.htm#TOC"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ rbox.c
+ Generate input points for qhull.
+
+ notes:
+ 50 points generated for 'rbox D4'
+
+ This code needs a full rewrite. It needs separate procedures for each
+ distribution with common, helper procedures.
+
+ WARNING:
+ incorrect range if qh_RANDOMmax is defined wrong (user.h)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <limits.h>
+#include <time.h>
+
+#include "user.h"
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+#endif
+
+#ifdef _MSC_VER /* Microsoft Visual C++ */
+#pragma warning( disable : 4244) /* conversion from double to int */
+#endif
+
+#define MINVALUE 0.8
+#define MAXdim 200
+#define PI 3.1415926535897932384
+#define DEFAULTzbox 1e6
+
+char prompt[]= "\n\
+-rbox- generate various point distributions. Default is random in cube.\n\
+\n\
+args (any order, space separated): Version: 2001/06/24\n\
+ 3000 number of random points in cube, lens, spiral, sphere or grid\n\
+ D3 dimension 3-d\n\
+ c add a unit cube to the output ('c G2.0' sets size)\n\
+ d add a unit diamond to the output ('d G2.0' sets size)\n\
+ l generate a regular 3-d spiral\n\
+ r generate a regular polygon, ('r s Z1 G0.1' makes a cone)\n\
+ s generate cospherical points\n\
+ x generate random points in simplex, may use 'r' or 'Wn'\n\
+ y same as 'x', plus simplex\n\
+ Pn,m,r add point [n,m,r] first, pads with 0\n\
+\n\
+ Ln lens distribution of radius n. Also 's', 'r', 'G', 'W'.\n\
+ Mn,m,r lattice (Mesh) rotated by [n,-m,0], [m,n,0], [0,0,r], ...\n\
+ '27 M1,0,1' is {0,1,2} x {0,1,2} x {0,1,2}. Try 'M3,4 z'.\n\
+ W0.1 random distribution within 0.1 of the cube's or sphere's surface\n\
+ Z0.5 s random points in a 0.5 disk projected to a sphere\n\
+ Z0.5 s G0.6 same as Z0.5 within a 0.6 gap\n\
+\n\
+ Bn bounding box coordinates, default %2.2g\n\
+ h output as homogeneous coordinates for cdd\n\
+ n remove command line from the first line of output\n\
+ On offset coordinates by n\n\
+ t use time as the random number seed (default is command line)\n\
+ tn use n as the random number seed\n\
+ z print integer coordinates, default 'Bn' is %2.2g\n\
+";
+
+/* ------------------------------ prototypes ----------------*/
+int roundi( double a);
+void out1( double a);
+void out2n( double a, double b);
+void out3n( double a, double b, double c);
+int qh_rand( void);
+void qh_srand( int seed);
+
+
+/* ------------------------------ globals -------------------*/
+
+ FILE *fp;
+ int isinteger= 0;
+ double out_offset= 0.0;
+
+
+/*--------------------------------------------
+-rbox- main procedure of rbox application
+*/
+int main(int argc, char **argv) {
+ int i,j,k;
+ int gendim;
+ int cubesize, diamondsize, seed=0, count, apex;
+ int dim=3 , numpoints= 0, totpoints, addpoints=0;
+ int issphere=0, isaxis=0, iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
+ int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0, istime=0;
+ int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
+ double width=0.0, gap=0.0, radius= 0.0;
+ double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
+ double *simplex, *simplexp;
+ int nthroot, mult[MAXdim];
+ double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
+ double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
+ double box= qh_DEFAULTbox; /* scale all numbers before output */
+ double randmax= qh_RANDOMmax;
+ char command[200], *s, seedbuf[200];
+ time_t timedata;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= False;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf ( stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+ if (argc == 1) {
+ printf (prompt, box, DEFAULTzbox);
+ exit(1);
+ }
+ if ((s = strrchr( argv[0], '\\'))) /* Borland gives full path */
+ strcpy (command, s+1);
+ else
+ strcpy (command, argv[0]);
+ if ((s= strstr (command, ".EXE"))
+ || (s= strstr (command, ".exe")))
+ *s= '\0';
+ /* ============= read flags =============== */
+ for (i=1; i < argc; i++) {
+ if (strlen (command) + strlen(argv[i]) + 1 < sizeof(command) ) {
+ strcat (command, " ");
+ strcat (command, argv[i]);
+ }
+ if (isdigit (argv[i][0])) {
+ numpoints= atoi (argv[i]);
+ continue;
+ }
+ if (argv[i][0] == '-')
+ (argv[i])++;
+ switch (argv[i][0]) {
+ case 'c':
+ addcube= 1;
+ if (i+1 < argc && argv[i+1][0] == 'G')
+ cube= (double) atof (&argv[++i][1]);
+ break;
+ case 'd':
+ adddiamond= 1;
+ if (i+1 < argc && argv[i+1][0] == 'G')
+ diamond= (double) atof (&argv[++i][1]);
+ break;
+ case 'h':
+ iscdd= 1;
+ break;
+ case 'l':
+ isspiral= 1;
+ break;
+ case 'n':
+ NOcommand= 1;
+ break;
+ case 'r':
+ isregular= 1;
+ break;
+ case 's':
+ issphere= 1;
+ break;
+ case 't':
+ istime= 1;
+ if (isdigit (argv[i][1]))
+ seed= atoi (&argv[i][1]);
+ else {
+ seed= time (&timedata);
+ sprintf (seedbuf, "%d", seed);
+ strcat (command, seedbuf);
+ }
+ break;
+ case 'x':
+ issimplex= 1;
+ break;
+ case 'y':
+ issimplex2= 1;
+ break;
+ case 'z':
+ isinteger= 1;
+ break;
+ case 'B':
+ box= (double) atof (&argv[i][1]);
+ isbox= 1;
+ break;
+ case 'D':
+ dim= atoi (&argv[i][1]);
+ if (dim < 1
+ || dim > MAXdim) {
+ fprintf (stderr, "rbox error: dim %d too large or too small\n", dim);
+ exit (1);
+ }
+ break;
+ case 'G':
+ if (argv[i][1])
+ gap= (double) atof (&argv[i][1]);
+ else
+ gap= 0.5;
+ isgap= 1;
+ break;
+ case 'L':
+ if (argv[i][1])
+ radius= (double) atof (&argv[i][1]);
+ else
+ radius= 10;
+ islens= 1;
+ break;
+ case 'M':
+ ismesh= 1;
+ s= argv[i]+1;
+ if (*s)
+ meshn= strtod (s, &s);
+ if (*s == ',')
+ meshm= strtod (++s, &s);
+ else
+ meshm= 0.0;
+ if (*s == ',')
+ meshr= strtod (++s, &s);
+ else
+ meshr= sqrt (meshn*meshn + meshm*meshm);
+ if (*s) {
+ fprintf (stderr, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
+ meshn= 3.0, meshm=4.0, meshr=5.0;
+ }
+ break;
+ case 'O':
+ out_offset= (double) atof (&argv[i][1]);
+ break;
+ case 'P':
+ addpoints++;
+ break;
+ case 'W':
+ width= (double) atof (&argv[i][1]);
+ iswidth= 1;
+ break;
+ case 'Z':
+ if (argv[i][1])
+ radius= (double) atof (&argv[i][1]);
+ else
+ radius= 1.0;
+ isaxis= 1;
+ break;
+ default:
+ fprintf (stderr, "rbox warning: unknown flag %s.\nExecute 'rbox' without arguments for documentation.\n", argv[i]);
+ }
+ }
+ /* ============= defaults, constants, and sizes =============== */
+ if (isinteger && !isbox)
+ box= DEFAULTzbox;
+ if (addcube) {
+ cubesize= floor(ldexp(1.0,dim)+0.5);
+ if (cube == 0.0)
+ cube= box;
+ }else
+ cubesize= 0;
+ if (adddiamond) {
+ diamondsize= 2*dim;
+ if (diamond == 0.0)
+ diamond= box;
+ }else
+ diamondsize= 0;
+ if (islens) {
+ if (isaxis) {
+ fprintf (stderr, "rbox error: can not combine 'Ln' with 'Zn'\n");
+ exit(1);
+ }
+ if (radius <= 1.0) {
+ fprintf (stderr, "rbox error: lens radius %.2g should be greater than 1.0\n",
+ radius);
+ exit(1);
+ }
+ lensangle= asin (1.0/radius);
+ lensbase= radius * cos (lensangle);
+ }
+ if (!numpoints) {
+ if (issimplex2)
+ ; /* ok */
+ else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
+ fprintf (stderr, "rbox error: missing count\n");
+ exit(1);
+ }else if (adddiamond + addcube + addpoints)
+ ; /* ok */
+ else {
+ numpoints= 50; /* ./rbox D4 is the test case */
+ issphere= 1;
+ }
+ }
+ if ((issimplex + islens + isspiral + ismesh > 1)
+ || (issimplex + issphere + isspiral + ismesh > 1)) {
+ fprintf (stderr, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
+ exit(1);
+ }
+ fp= stdout;
+ /* ============= print header with total points =============== */
+ if (issimplex || ismesh)
+ totpoints= numpoints;
+ else if (issimplex2)
+ totpoints= numpoints+dim+1;
+ else if (isregular) {
+ totpoints= numpoints;
+ if (dim == 2) {
+ if (islens)
+ totpoints += numpoints - 2;
+ }else if (dim == 3) {
+ if (islens)
+ totpoints += 2 * numpoints;
+ else if (isgap)
+ totpoints += 1 + numpoints;
+ else
+ totpoints += 2;
+ }
+ }else
+ totpoints= numpoints + isaxis;
+ totpoints += cubesize + diamondsize + addpoints;
+ if (iscdd)
+ fprintf(fp, "%s\nbegin\n %d %d %s\n",
+ NOcommand ? "" : command,
+ totpoints, dim+1,
+ isinteger ? "integer" : "real");
+ else if (NOcommand)
+ fprintf(fp, "%d\n%d\n", dim, totpoints);
+ else
+ fprintf(fp, "%d %s\n%d\n", dim, command, totpoints);
+ /* ============= seed randoms =============== */
+ if (istime == 0) {
+ for (s=command; *s; s++) {
+ if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
+ i= 'x';
+ else
+ i= *s;
+ seed= 11*seed + i;
+ }
+ } /* else, seed explicitly set to n or to time */
+ qh_RANDOMseed_(seed);
+ /* ============= explicit points =============== */
+ for (i=1; i < argc; i++) {
+ if (argv[i][0] == 'P') {
+ s= argv[i]+1;
+ count= 0;
+ if (iscdd)
+ out1( 1.0);
+ while (*s) {
+ out1( strtod (s, &s));
+ count++;
+ if (*s) {
+ if (*s++ != ',') {
+ fprintf (stderr, "rbox error: missing comma after coordinate in %s\n\n", argv[i]);
+ exit (1);
+ }
+ }
+ }
+ if (count < dim) {
+ for (k= dim-count; k--; )
+ out1( 0.0);
+ }else if (count > dim) {
+ fprintf (stderr, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
+ count, dim, argv[i]);
+ exit (1);
+ }
+ fprintf (fp, "\n");
+ }
+ }
+ /* ============= simplex distribution =============== */
+ if (issimplex+issimplex2) {
+ if (!(simplex= malloc( dim * (dim+1) * sizeof(double)))) {
+ fprintf (stderr, "insufficient memory for simplex\n");
+ exit(0);
+ }
+ simplexp= simplex;
+ if (isregular) {
+ for (i= 0; i<dim; i++) {
+ for (k= 0; k<dim; k++)
+ *(simplexp++)= i==k ? 1.0 : 0.0;
+ }
+ for (k= 0; k<dim; k++)
+ *(simplexp++)= -1.0;
+ }else {
+ for (i= 0; i<dim+1; i++) {
+ for (k= 0; k<dim; k++) {
+ randr= qh_RANDOMint;
+ *(simplexp++)= 2.0 * randr/randmax - 1.0;
+ }
+ }
+ }
+ if (issimplex2) {
+ simplexp= simplex;
+ for (i= 0; i<dim+1; i++) {
+ if (iscdd)
+ out1( 1.0);
+ for (k= 0; k<dim; k++)
+ out1( *(simplexp++) * box);
+ fprintf (fp, "\n");
+ }
+ }
+ for (j= 0; j<numpoints; j++) {
+ if (iswidth)
+ apex= qh_RANDOMint % (dim+1);
+ else
+ apex= -1;
+ for (k= 0; k<dim; k++)
+ coord[k]= 0.0;
+ norm= 0.0;
+ for (i= 0; i<dim+1; i++) {
+ randr= qh_RANDOMint;
+ factor= randr/randmax;
+ if (i == apex)
+ factor *= width;
+ norm += factor;
+ for (k= 0; k<dim; k++) {
+ simplexp= simplex + i*dim + k;
+ coord[k] += factor * (*simplexp);
+ }
+ }
+ for (k= 0; k<dim; k++)
+ coord[k] /= norm;
+ if (iscdd)
+ out1( 1.0);
+ for (k=0; k < dim; k++)
+ out1( coord[k] * box);
+ fprintf (fp, "\n");
+ }
+ isregular= 0; /* continue with isbox */
+ numpoints= 0;
+ }
+ /* ============= mesh distribution =============== */
+ if (ismesh) {
+ nthroot= pow (numpoints, 1.0/dim) + 0.99999;
+ for (k= dim; k--; )
+ mult[k]= 0;
+ for (i= 0; i < numpoints; i++) {
+ for (k= 0; k < dim; k++) {
+ if (k == 0)
+ out1( mult[0] * meshn + mult[1] * (-meshm));
+ else if (k == 1)
+ out1( mult[0] * meshm + mult[1] * meshn);
+ else
+ out1( mult[k] * meshr );
+ }
+ fprintf (fp, "\n");
+ for (k= 0; k < dim; k++) {
+ if (++mult[k] < nthroot)
+ break;
+ mult[k]= 0;
+ }
+ }
+ }
+
+ /* ============= regular points for 's' =============== */
+ else if (isregular && !islens) {
+ if (dim != 2 && dim != 3) {
+ fprintf(stderr, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+ exit(1);
+ }
+ if (!isaxis || radius == 0.0) {
+ isaxis= 1;
+ radius= 1.0;
+ }
+ if (dim == 3) {
+ if (iscdd)
+ out1( 1.0);
+ out3n( 0.0, 0.0, -box);
+ if (!isgap) {
+ if (iscdd)
+ out1( 1.0);
+ out3n( 0.0, 0.0, box);
+ }
+ }
+ angle= 0.0;
+ anglediff= 2.0 * PI/numpoints;
+ for (i=0; i < numpoints; i++) {
+ angle += anglediff;
+ x= radius * cos (angle);
+ y= radius * sin (angle);
+ if (dim == 2) {
+ if (iscdd)
+ out1( 1.0);
+ out2n( x*box, y*box);
+ }else {
+ norm= sqrt (1.0 + x*x + y*y);
+ if (iscdd)
+ out1( 1.0);
+ out3n( box*x/norm, box*y/norm, box/norm);
+ if (isgap) {
+ x *= 1-gap;
+ y *= 1-gap;
+ norm= sqrt (1.0 + x*x + y*y);
+ if (iscdd)
+ out1( 1.0);
+ out3n( box*x/norm, box*y/norm, box/norm);
+ }
+ }
+ }
+ }
+ /* ============= regular points for 'r Ln D2' =============== */
+ else if (isregular && islens && dim == 2) {
+ double cos_0;
+
+ angle= lensangle;
+ anglediff= 2 * lensangle/(numpoints - 1);
+ cos_0= cos (lensangle);
+ for (i=0; i < numpoints; i++, angle -= anglediff) {
+ x= radius * sin (angle);
+ y= radius * (cos (angle) - cos_0);
+ if (iscdd)
+ out1( 1.0);
+ out2n( x*box, y*box);
+ if (i != 0 && i != numpoints - 1) {
+ if (iscdd)
+ out1( 1.0);
+ out2n( x*box, -y*box);
+ }
+ }
+ }
+ /* ============= regular points for 'r Ln D3' =============== */
+ else if (isregular && islens && dim != 2) {
+ if (dim != 3) {
+ fprintf(stderr, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+ exit(1);
+ }
+ angle= 0.0;
+ anglediff= 2* PI/numpoints;
+ if (!isgap) {
+ isgap= 1;
+ gap= 0.5;
+ }
+ offset= sqrt (radius * radius - (1-gap)*(1-gap)) - lensbase;
+ for (i=0; i < numpoints; i++, angle += anglediff) {
+ x= cos (angle);
+ y= sin (angle);
+ if (iscdd)
+ out1( 1.0);
+ out3n( box*x, box*y, 0);
+ x *= 1-gap;
+ y *= 1-gap;
+ if (iscdd)
+ out1( 1.0);
+ out3n( box*x, box*y, box * offset);
+ if (iscdd)
+ out1( 1.0);
+ out3n( box*x, box*y, -box * offset);
+ }
+ }
+ /* ============= apex of 'Zn' distribution + gendim =============== */
+ else {
+ if (isaxis) {
+ gendim= dim-1;
+ if (iscdd)
+ out1( 1.0);
+ for (j=0; j < gendim; j++)
+ out1( 0.0);
+ out1( -box);
+ fprintf (fp, "\n");
+ }else if (islens)
+ gendim= dim-1;
+ else
+ gendim= dim;
+ /* ============= generate random point in unit cube =============== */
+ for (i=0; i < numpoints; i++) {
+ norm= 0.0;
+ for (j=0; j < gendim; j++) {
+ randr= qh_RANDOMint;
+ coord[j]= 2.0 * randr/randmax - 1.0;
+ norm += coord[j] * coord[j];
+ }
+ norm= sqrt (norm);
+ /* ============= dim-1 point of 'Zn' distribution ========== */
+ if (isaxis) {
+ if (!isgap) {
+ isgap= 1;
+ gap= 1.0;
+ }
+ randr= qh_RANDOMint;
+ rangap= 1.0 - gap * randr/randmax;
+ factor= radius * rangap / norm;
+ for (j=0; j<gendim; j++)
+ coord[j]= factor * coord[j];
+ /* ============= dim-1 point of 'Ln s' distribution =========== */
+ }else if (islens && issphere) {
+ if (!isgap) {
+ isgap= 1;
+ gap= 1.0;
+ }
+ randr= qh_RANDOMint;
+ rangap= 1.0 - gap * randr/randmax;
+ factor= rangap / norm;
+ for (j=0; j<gendim; j++)
+ coord[j]= factor * coord[j];
+ /* ============= dim-1 point of 'Ln' distribution ========== */
+ }else if (islens && !issphere) {
+ if (!isgap) {
+ isgap= 1;
+ gap= 1.0;
+ }
+ j= qh_RANDOMint % gendim;
+ if (coord[j] < 0)
+ coord[j]= -1.0 - coord[j] * gap;
+ else
+ coord[j]= 1.0 - coord[j] * gap;
+ /* ============= point of 'l' distribution =============== */
+ }else if (isspiral) {
+ if (dim != 3) {
+ fprintf(stderr, "rbox error: spiral distribution is available only in 3d\n\n");
+ exit(1);
+ }
+ coord[0]= cos(2*PI*i/(numpoints - 1));
+ coord[1]= sin(2*PI*i/(numpoints - 1));
+ coord[2]= 2.0*(double)i/(double)(numpoints-1) - 1.0;
+ /* ============= point of 's' distribution =============== */
+ }else if (issphere) {
+ factor= 1.0/norm;
+ if (iswidth) {
+ randr= qh_RANDOMint;
+ factor *= 1.0 - width * randr/randmax;
+ }
+ for (j=0; j<dim; j++)
+ coord[j]= factor * coord[j];
+ }
+ /* ============= project 'Zn s' point in to sphere =============== */
+ if (isaxis && issphere) {
+ coord[dim-1]= 1.0;
+ norm= 1.0;
+ for (j=0; j<gendim; j++)
+ norm += coord[j] * coord[j];
+ norm= sqrt (norm);
+ for (j=0; j<dim; j++)
+ coord[j]= coord[j] / norm;
+ if (iswidth) {
+ randr= qh_RANDOMint;
+ coord[dim-1] *= 1 - width * randr/randmax;
+ }
+ /* ============= project 'Zn' point onto cube =============== */
+ }else if (isaxis && !issphere) { /* not very interesting */
+ randr= qh_RANDOMint;
+ coord[dim-1]= 2.0 * randr/randmax - 1.0;
+ /* ============= project 'Ln' point out to sphere =============== */
+ }else if (islens) {
+ coord[dim-1]= lensbase;
+ for (j=0, norm= 0; j<dim; j++)
+ norm += coord[j] * coord[j];
+ norm= sqrt (norm);
+ for (j=0; j<dim; j++)
+ coord[j]= coord[j] * radius/ norm;
+ coord[dim-1] -= lensbase;
+ if (iswidth) {
+ randr= qh_RANDOMint;
+ coord[dim-1] *= 1 - width * randr/randmax;
+ }
+ if (qh_RANDOMint > randmax/2)
+ coord[dim-1]= -coord[dim-1];
+ /* ============= project 'Wn' point toward boundary =============== */
+ }else if (iswidth && !issphere) {
+ j= qh_RANDOMint % gendim;
+ if (coord[j] < 0)
+ coord[j]= -1.0 - coord[j] * width;
+ else
+ coord[j]= 1.0 - coord[j] * width;
+ }
+ /* ============= write point =============== */
+ if (iscdd)
+ out1( 1.0);
+ for (k=0; k < dim; k++)
+ out1( coord[k] * box);
+ fprintf (fp, "\n");
+ }
+ }
+ /* ============= write cube vertices =============== */
+ if (addcube) {
+ for (j=0; j<cubesize; j++) {
+ if (iscdd)
+ out1( 1.0);
+ for (k=dim-1; k>=0; k--) {
+ if (j & ( 1 << k))
+ out1( cube);
+ else
+ out1( -cube);
+ }
+ fprintf (fp, "\n");
+ }
+ }
+ /* ============= write diamond vertices =============== */
+ if (adddiamond) {
+ for (j=0; j<diamondsize; j++) {
+ if (iscdd)
+ out1( 1.0);
+ for (k=dim-1; k>=0; k--) {
+ if (j/2 != k)
+ out1( 0.0);
+ else if (j & 0x1)
+ out1( diamond);
+ else
+ out1( -diamond);
+ }
+ fprintf (fp, "\n");
+ }
+ }
+ if (iscdd)
+ fprintf (fp, "end\nhull\n");
+ return 0;
+ } /* rbox */
+
+/*------------------------------------------------
+-outxxx - output functions
+*/
+int roundi( double a) {
+ if (a < 0.0) {
+ if (a - 0.5 < INT_MIN) {
+ fprintf(stderr, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
+ exit (1);
+ }
+ return a - 0.5;
+ }else {
+ if (a + 0.5 > INT_MAX) {
+ fprintf(stderr, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
+ exit (1);
+ }
+ return a + 0.5;
+ }
+} /* roundi */
+
+void out1(double a) {
+
+ if (isinteger)
+ fprintf(fp, "%d ", roundi( a+out_offset));
+ else
+ fprintf(fp, qh_REAL_1, a+out_offset);
+} /* out1 */
+
+void out2n( double a, double b) {
+
+ if (isinteger)
+ fprintf(fp, "%d %d\n", roundi(a+out_offset), roundi(b+out_offset));
+ else
+ fprintf(fp, qh_REAL_2n, a+out_offset, b+out_offset);
+} /* out2n */
+
+void out3n( double a, double b, double c) {
+
+ if (isinteger)
+ fprintf(fp, "%d %d %d\n", roundi(a+out_offset), roundi(b+out_offset), roundi(c+out_offset));
+ else
+ fprintf(fp, qh_REAL_3n, a+out_offset, b+out_offset, c+out_offset);
+} /* out3n */
+
+/*-------------------------------------------------
+-rand & srand- generate pseudo-random number between 1 and 2^31 -2
+ from Park & Miller's minimimal standard random number generator
+ Communications of the ACM, 31:1192-1201, 1988.
+notes:
+ does not use 0 or 2^31 -1
+ this is silently enforced by qh_srand()
+ copied from geom2.c
+*/
+static int seed = 1; /* global static */
+
+int qh_rand( void) {
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773 /* m div a */
+#define qh_rand_r 2836 /* m mod a */
+ int lo, hi, test;
+
+ hi = seed / qh_rand_q; /* seed div q */
+ lo = seed % qh_rand_q; /* seed mod q */
+ test = qh_rand_a * lo - qh_rand_r * hi;
+ if (test > 0)
+ seed= test;
+ else
+ seed= test + qh_rand_m;
+ return seed;
+} /* rand */
+
+void qh_srand( int newseed) {
+ if (newseed < 1)
+ seed= 1;
+ else if (newseed >= qh_rand_m)
+ seed= qh_rand_m - 1;
+ else
+ seed= newseed;
+} /* qh_srand */
+
diff --git a/extern/qhull/src/stat.c b/extern/qhull/src/stat.c
new file mode 100644
index 00000000000..ede0323cb88
--- /dev/null
+++ b/extern/qhull/src/stat.c
@@ -0,0 +1,700 @@
+/*<html><pre> -<a href="qh-stat.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ stat.c
+ contains all statistics that are collected for qhull
+
+ see qh-stat.htm and stat.h
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*============ global data structure ==========*/
+
+#if qh_QHpointer
+qhstatT *qh_qhstat=NULL; /* global data structure */
+#else
+qhstatT qh_qhstat; /* add "={0}" if this causes a compiler error */
+#endif
+
+/*========== functions in alphabetic order ================*/
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="allstatA">-</a>
+
+ qh_allstatA()
+ define statistics in groups of 20
+
+ notes:
+ (otherwise, 'gcc -O2' uses too much memory)
+ uses qhstat.next
+*/
+void qh_allstatA (void) {
+
+ /* zdef_(type,name,doc,average) */
+ zzdef_(zdoc, Zdoc2, "precision statistics", -1);
+ zdef_(zinc, Znewvertex, NULL, -1);
+ zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet (not 0s)", Znewvertex);
+ zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
+ zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
+ zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
+ zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
+
+ qhstat precision= qhstat next; /* call qh_precision for each of these */
+ zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
+ zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
+ zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
+ zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
+ zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
+ zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
+ zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
+ zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
+ zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
+ zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
+ zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
+}
+void qh_allstatB (void) {
+ zzdef_(zdoc, Zdoc1, "summary information", -1);
+ zdef_(zinc, Zvertices, "number of vertices in output", -1);
+ zdef_(zinc, Znumfacets, "number of facets in output", -1);
+ zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
+ zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
+ zdef_(zinc, Znumridges, "number of ridges in output", -1);
+ zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
+ zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
+ zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
+ zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
+ zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
+ zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
+ zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
+ zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
+ zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
+ zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
+ zzdef_(zinc, Zsetplane, "facets created altogether", -1);
+ zdef_(zinc, Ztotridges, "ridges created altogether", -1);
+ zdef_(zinc, Zpostfacets, "facets before post merge", -1);
+ zdef_(zadd, Znummergetot, "average merges per facet (at most 511)", Znumfacets);
+ zdef_(zmax, Znummergemax, " maximum merges for a facet (at most 511)", -1);
+ zdef_(zinc, Zangle, NULL, -1);
+ zdef_(wadd, Wangle, "average angle (cosine) of facet normals for all ridges", Zangle);
+ zdef_(wmax, Wanglemax, " maximum angle (cosine) of facet normals across a ridge", -1);
+ zdef_(wmin, Wanglemin, " minimum angle (cosine) of facet normals across a ridge", -1);
+ zdef_(wadd, Wareatot, "total area of facets", -1);
+ zdef_(wmax, Wareamax, " maximum facet area", -1);
+ zdef_(wmin, Wareamin, " minimum facet area", -1);
+}
+void qh_allstatC (void) {
+ zdef_(zdoc, Zdoc9, "build hull statistics", -1);
+ zzdef_(zinc, Zprocessed, "points processed", -1);
+ zzdef_(zinc, Zretry, "retries due to precision problems", -1);
+ zdef_(wmax, Wretrymax, " max. random joggle", -1);
+ zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
+ zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
+ zdef_(zinc, Zinsidevisible, " ave. visible facets without an horizon neighbor", Zprocessed);
+ zdef_(zadd, Zvisfacettot, " ave. facets deleted per iteration", Zprocessed);
+ zdef_(zmax, Zvisfacetmax, " maximum", -1);
+ zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
+ zdef_(zmax, Zvisvertexmax, " maximum", -1);
+ zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
+ zdef_(zadd, Znewfacettot, "ave. new or merged facets per iteration", Zprocessed);
+ zdef_(zmax, Znewfacetmax, " maximum (includes initial simplex)", -1);
+ zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
+ zdef_(wadd, Wnewbalance2, " standard deviation", -1);
+ zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
+ zdef_(wadd, Wpbalance2, " standard deviation", -1);
+ zdef_(zinc, Zpbalance, " number of trials", -1);
+ zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
+ zdef_(zinc, Zdetsimplex, "determinants computed (area & initial hull)", -1);
+ zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
+ zdef_(zinc, Znotmax, "points ignored (not above max_outside)", -1);
+ zdef_(zinc, Znotgood, "points ignored (not above a good facet)", -1);
+ zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
+ zdef_(zinc, Zgoodfacet, "good facets found", -1);
+ zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
+ zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
+ zdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
+ zzdef_(zinc, Zcheckpart, " ave. distance tests per check", Ztotcheck);
+}
+void qh_allstatD(void) {
+ zdef_(zdoc, Zdoc4, "partitioning statistics (see previous for outer planes)", -1);
+ zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
+ zdef_(zmax, Zdelvertexmax, " maximum vertices deleted per iteration", -1);
+ zdef_(zinc, Zfindbest, "calls to findbest", -1);
+ zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
+ zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
+ zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
+ zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
+ zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
+ zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
+ zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
+ zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
+ zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
+ zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
+ zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
+ zdef_(zinc, Zfindjump, " ave. clearly better", Zfindhorizon);
+ zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
+ zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
+ zdef_(zinc, Zpartflip, " repartitioned coplanar points for flipped orientation", -1);
+ zdef_(zinc, Zpartinside, "inside points", -1);
+ zdef_(zinc, Zpartnear, " inside points kept with a facet", -1);
+ zdef_(zinc, Zcoplanarinside, " inside points that were coplanar with a facet", -1);
+ zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
+}
+void qh_allstatE(void) {
+ zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
+ zdef_(zinc, Ztotpartition, "partitions of a point", -1);
+ zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
+ zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
+ zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
+ zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
+ zdef_(zinc, Zdistio, "distance tests for output", -1);
+ zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
+ zdef_(zinc, Zdistplane, "total number of distance tests", -1);
+ zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
+ zzdef_(zinc, Zpartcoplanar, " distance tests for these partitions", -1);
+ zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
+}
+void qh_allstatE2(void) {
+ zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
+ zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
+ zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
+ zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
+ zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
+ zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
+ zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
+
+ zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
+ zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
+ zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
+ zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
+ zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
+ zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
+ zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
+ zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
+ zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
+}
+void qh_allstatF(void) {
+ zdef_(zdoc, Zdoc7, "statistics for merging", -1);
+ zdef_(zinc, Zpremergetot, "merge iterations", -1);
+ zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
+ zdef_(zadd, Zmergeinitmax, " maximum", -1);
+ zdef_(zadd, Zmergesettot, " ave. additional non-convex ridges per iteration", Zpremergetot);
+ zdef_(zadd, Zmergesetmax, " maximum additional in one pass", -1);
+ zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
+ zdef_(zadd, Zmergesettot2, " additional non-convex ridges", -1);
+ zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet (w/roundoff)", -1);
+ zdef_(wmin, Wminvertex, "max distance of merged vertex below facet (or roundoff)", -1);
+ zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
+ zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
+ zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
+ zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
+ zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
+ zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
+ zzdef_(zadd, Zcyclefacettot, " ave. facets per cycle", Zcyclehorizon);
+ zdef_(zmax, Zcyclefacetmax, " max. facets", -1);
+ zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
+ zdef_(zinc, Zmergenew, "new facets merged", -1);
+ zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
+ zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
+ zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
+ zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
+ zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
+ zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
+ zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
+}
+void qh_allstatG(void) {
+ zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
+ zdef_(wadd, Wacoplanartot, " average merge distance", Zacoplanar);
+ zdef_(wmax, Wacoplanarmax, " maximum merge distance", -1);
+ zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
+ zdef_(wadd, Wcoplanartot, " average merge distance", Zcoplanar);
+ zdef_(wmax, Wcoplanarmax, " maximum merge distance", -1);
+ zdef_(zinc, Zconcave, "merges due to concave facets", -1);
+ zdef_(wadd, Wconcavetot, " average merge distance", Zconcave);
+ zdef_(wmax, Wconcavemax, " maximum merge distance", -1);
+ zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
+ zdef_(wadd, Wavoidoldtot, " average merge distance", Zavoidold);
+ zdef_(wmax, Wavoidoldmax, " maximum merge distance", -1);
+ zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
+ zdef_(wadd, Wdegentot, " average merge distance", Zdegen);
+ zdef_(wmax, Wdegenmax, " maximum merge distance", -1);
+ zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
+ zdef_(wadd, Wflippedtot, " average merge distance", Zflipped);
+ zdef_(wmax, Wflippedmax, " maximum merge distance", -1);
+ zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
+ zdef_(wadd, Wduplicatetot, " average merge distance", Zduplicate);
+ zdef_(wmax, Wduplicatemax, " maximum merge distance", -1);
+}
+void qh_allstatH(void) {
+ zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
+ zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
+ zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
+ zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
+ zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
+ zdef_(zinc, Zdupridge, " duplicate ridges detected", -1);
+ zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
+ zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
+ zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
+ zdef_(zinc, Zdelfacetdup, " facets deleted because of no neighbors", -1);
+ zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
+ zdef_(zinc, Zremvertexdel, " deleted", -1);
+ zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
+ zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
+ zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
+ zdef_(zadd, Zintersecttot, " ave. number found per vertex", Zintersect);
+ zdef_(zmax, Zintersectmax, " max. found for a vertex", -1);
+ zdef_(zinc, Zvertexridge, NULL, -1);
+ zdef_(zadd, Zvertexridgetot, " ave. number of ridges per tested vertex", Zvertexridge);
+ zdef_(zmax, Zvertexridgemax, " max. number of ridges per tested vertex", -1);
+
+ zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
+ zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
+ zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
+ zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
+ zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
+} /* allstat */
+
+void qh_allstatI(void) {
+ qhstat vridges= qhstat next;
+ zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
+ zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
+ zzdef_(wadd, Wridge, " ave. distance to ridge", Zridge);
+ zzdef_(wmax, Wridgemax, " max. distance to ridge", -1);
+ zzdef_(zinc, Zridgemid, "bounded ridges", -1);
+ zzdef_(wadd, Wridgemid, " ave. distance of midpoint to ridge", Zridgemid);
+ zzdef_(wmax, Wridgemidmax, " max. distance of midpoint to ridge", -1);
+ zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
+ zzdef_(wadd, Wridgeok, " ave. angle to ridge", Zridgeok);
+ zzdef_(wmax, Wridgeokmax, " max. angle to ridge", -1);
+ zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
+ zzdef_(wadd, Wridge0, " ave. angle to ridge", Zridge0);
+ zzdef_(wmax, Wridge0max, " max. angle to ridge", -1);
+
+ zdef_(zdoc, Zdoc12, "Triangulation statistics (Qt)", -1);
+ zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
+ zdef_(zadd, Ztricoplanartot, " ave. new facets created (may be deleted)", Ztricoplanar);
+ zdef_(zmax, Ztricoplanarmax, " max. new facets created", -1);
+ zdef_(zinc, Ztrinull, "null new facets deleted (duplicated vertex)", -1);
+ zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted (same vertices)", -1);
+ zdef_(zinc, Ztridegen, "degenerate new facets in output (same ridge)", -1);
+} /* allstat */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="allstatistics">-</a>
+
+ qh_allstatistics()
+ reset printed flag for all statistics
+*/
+void qh_allstatistics (void) {
+ int i;
+
+ for (i=ZEND; i--; )
+ qhstat printed[i]= False;
+} /* allstatistics */
+
+#if qh_KEEPstatistics
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="collectstatistics">-</a>
+
+ qh_collectstatistics()
+ collect statistics for qh.facet_list
+
+*/
+void qh_collectstatistics (void) {
+ facetT *facet, *neighbor, **neighborp;
+ vertexT *vertex, **vertexp;
+ realT dotproduct, dist;
+ int sizneighbors, sizridges, sizvertices, i;
+
+ qh old_randomdist= qh RANDOMdist;
+ qh RANDOMdist= False;
+ zval_(Zmempoints)= qh num_points * qh normal_size +
+ sizeof (qhT) + sizeof (qhstatT);
+ zval_(Zmemfacets)= 0;
+ zval_(Zmemridges)= 0;
+ zval_(Zmemvertices)= 0;
+ zval_(Zangle)= 0;
+ wval_(Wangle)= 0.0;
+ zval_(Znumridges)= 0;
+ zval_(Znumfacets)= 0;
+ zval_(Znumneighbors)= 0;
+ zval_(Znumvertices)= 0;
+ zval_(Znumvneighbors)= 0;
+ zval_(Znummergetot)= 0;
+ zval_(Znummergemax)= 0;
+ zval_(Zvertices)= qh num_vertices - qh_setsize (qh del_vertices);
+ if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
+ wmax_(Wmaxoutside, qh max_outside);
+ if (qh MERGING)
+ wmin_(Wminvertex, qh min_vertex);
+ FORALLfacets
+ facet->seen= False;
+ if (qh DELAUNAY) {
+ FORALLfacets {
+ if (facet->upperdelaunay != qh UPPERdelaunay)
+ facet->seen= True; /* remove from angle statistics */
+ }
+ }
+ FORALLfacets {
+ if (facet->visible && qh NEWfacets)
+ continue;
+ sizvertices= qh_setsize (facet->vertices);
+ sizneighbors= qh_setsize (facet->neighbors);
+ sizridges= qh_setsize (facet->ridges);
+ zinc_(Znumfacets);
+ zadd_(Znumvertices, sizvertices);
+ zmax_(Zmaxvertices, sizvertices);
+ zadd_(Znumneighbors, sizneighbors);
+ zmax_(Zmaxneighbors, sizneighbors);
+ zadd_(Znummergetot, facet->nummerge);
+ i= facet->nummerge; /* avoid warnings */
+ zmax_(Znummergemax, i);
+ if (!facet->simplicial) {
+ if (sizvertices == qh hull_dim) {
+ zinc_(Znowsimplicial);
+ }else {
+ zinc_(Znonsimplicial);
+ }
+ }
+ if (sizridges) {
+ zadd_(Znumridges, sizridges);
+ zmax_(Zmaxridges, sizridges);
+ }
+ zadd_(Zmemfacets, sizeof (facetT) + qh normal_size + 2*sizeof (setT)
+ + SETelemsize * (sizneighbors + sizvertices));
+ if (facet->ridges) {
+ zadd_(Zmemridges,
+ sizeof (setT) + SETelemsize * sizridges + sizridges *
+ (sizeof (ridgeT) + sizeof (setT) + SETelemsize * (qh hull_dim-1))/2);
+ }
+ if (facet->outsideset)
+ zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->outsideset));
+ if (facet->coplanarset)
+ zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->coplanarset));
+ if (facet->seen) /* Delaunay upper envelope */
+ continue;
+ facet->seen= True;
+ FOREACHneighbor_(facet) {
+ if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
+ || neighbor->seen || !facet->normal || !neighbor->normal)
+ continue;
+ dotproduct= qh_getangle(facet->normal, neighbor->normal);
+ zinc_(Zangle);
+ wadd_(Wangle, dotproduct);
+ wmax_(Wanglemax, dotproduct)
+ wmin_(Wanglemin, dotproduct)
+ }
+ if (facet->normal) {
+ FOREACHvertex_(facet->vertices) {
+ zinc_(Zdiststat);
+ qh_distplane(vertex->point, facet, &dist);
+ wmax_(Wvertexmax, dist);
+ wmin_(Wvertexmin, dist);
+ }
+ }
+ }
+ FORALLvertices {
+ if (vertex->deleted)
+ continue;
+ zadd_(Zmemvertices, sizeof (vertexT));
+ if (vertex->neighbors) {
+ sizneighbors= qh_setsize (vertex->neighbors);
+ zadd_(Znumvneighbors, sizneighbors);
+ zmax_(Zmaxvneighbors, sizneighbors);
+ zadd_(Zmemvertices, sizeof (vertexT) + SETelemsize * sizneighbors);
+ }
+ }
+ qh RANDOMdist= qh old_randomdist;
+} /* collectstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="freestatistics">-</a>
+
+ qh_freestatistics( )
+ free memory used for statistics
+*/
+void qh_freestatistics (void) {
+
+#if qh_QHpointer
+ free (qh_qhstat);
+ qh_qhstat= NULL;
+#endif
+} /* freestatistics */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="initstatistics">-</a>
+
+ qh_initstatistics( )
+ allocate and initialize statistics
+
+ notes:
+ uses malloc() instead of qh_memalloc() since mem.c not set up yet
+*/
+void qh_initstatistics (void) {
+ int i;
+ realT realx;
+ int intx;
+
+#if qh_QHpointer
+ if (!(qh_qhstat= (qhstatT *)malloc (sizeof(qhstatT)))) {
+ fprintf (qhmem.ferr, "qhull error (qh_initstatistics): insufficient memory\n");
+ exit (1); /* can not use qh_errexit() */
+ }
+#endif
+
+ qhstat next= 0;
+ qh_allstatA();
+ qh_allstatB();
+ qh_allstatC();
+ qh_allstatD();
+ qh_allstatE();
+ qh_allstatE2();
+ qh_allstatF();
+ qh_allstatG();
+ qh_allstatH();
+ qh_allstatI();
+ if (qhstat next > sizeof(qhstat id)) {
+ fprintf (qhmem.ferr, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
+ qhstat.next %d should be <= sizeof(qhstat id) %ld\n", qhstat next, sizeof(qhstat id));
+#if 0 /* for locating error, Znumridges should be duplicated */
+ for (i=0; i < ZEND; i++) {
+ int j;
+ for (j=i+1; j < ZEND; j++) {
+ if (qhstat id[i] == qhstat id[j]) {
+ fprintf (qhmem.ferr, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
+ qhstat id[i], i, j);
+ }
+ }
+ }
+#endif
+ exit (1); /* can not use qh_errexit() */
+ }
+ qhstat init[zinc].i= 0;
+ qhstat init[zadd].i= 0;
+ qhstat init[zmin].i= INT_MAX;
+ qhstat init[zmax].i= INT_MIN;
+ qhstat init[wadd].r= 0;
+ qhstat init[wmin].r= REALmax;
+ qhstat init[wmax].r= -REALmax;
+ for (i=0; i < ZEND; i++) {
+ if (qhstat type[i] > ZTYPEreal) {
+ realx= qhstat init[(unsigned char)(qhstat type[i])].r;
+ qhstat stats[i].r= realx;
+ }else if (qhstat type[i] != zdoc) {
+ intx= qhstat init[(unsigned char)(qhstat type[i])].i;
+ qhstat stats[i].i= intx;
+ }
+ }
+} /* initstatistics */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="newstats">-</a>
+
+ qh_newstats( )
+ returns True if statistics for zdoc
+
+ returns:
+ next zdoc
+*/
+boolT qh_newstats (int index, int *nextindex) {
+ boolT isnew= False;
+ int start, i;
+
+ if (qhstat type[qhstat id[index]] == zdoc)
+ start= index+1;
+ else
+ start= index;
+ for (i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
+ if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
+ isnew= True;
+ }
+ *nextindex= i;
+ return isnew;
+} /* newstats */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="nostatistic">-</a>
+
+ qh_nostatistic( index )
+ true if no statistic to print
+*/
+boolT qh_nostatistic (int i) {
+
+ if ((qhstat type[i] > ZTYPEreal
+ &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
+ || (qhstat type[i] < ZTYPEreal
+ &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
+ return True;
+ return False;
+} /* nostatistic */
+
+#if qh_KEEPstatistics
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="printallstatistics">-</a>
+
+ qh_printallstatistics( fp, string )
+ print all statistics with header 'string'
+*/
+void qh_printallstatistics (FILE *fp, char *string) {
+
+ qh_allstatistics();
+ qh_collectstatistics();
+ qh_printstatistics (fp, string);
+ qh_memstatistics (fp);
+}
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="printstatistics">-</a>
+
+ qh_printstatistics( fp, string )
+ print statistics to a file with header 'string'
+ skips statistics with qhstat.printed[] (reset with qh_allstatistics)
+
+ see:
+ qh_printallstatistics()
+*/
+void qh_printstatistics (FILE *fp, char *string) {
+ int i, k;
+ realT ave;
+
+ if (qh num_points != qh num_vertices) {
+ wval_(Wpbalance)= 0;
+ wval_(Wpbalance2)= 0;
+ }else
+ wval_(Wpbalance2)= qh_stddev (zval_(Zpbalance), wval_(Wpbalance),
+ wval_(Wpbalance2), &ave);
+ wval_(Wnewbalance2)= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance),
+ wval_(Wnewbalance2), &ave);
+ fprintf (fp, "\n\
+%s\n\
+ qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command,
+ qh qhull_command, qh_VERSION, qh qhull_options);
+ fprintf (fp, "\nprecision constants:\n\
+ %6.2g max. abs. coordinate in the (transformed) input ('Qbd:n')\n\
+ %6.2g max. roundoff error for distance computation ('En')\n\
+ %6.2g max. roundoff error for angle computations\n\
+ %6.2g min. distance for outside points ('Wn')\n\
+ %6.2g min. distance for visible facets ('Vn')\n\
+ %6.2g max. distance for coplanar facets ('Un')\n\
+ %6.2g max. facet width for recomputing centrum and area\n\
+",
+ qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside,
+ qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
+ if (qh KEEPnearinside)
+ fprintf(fp, "\
+ %6.2g max. distance for near-inside points\n", qh NEARinside);
+ if (qh premerge_cos < REALmax/2) fprintf (fp, "\
+ %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
+ if (qh PREmerge) fprintf (fp, "\
+ %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
+ if (qh postmerge_cos < REALmax/2) fprintf (fp, "\
+ %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
+ if (qh POSTmerge) fprintf (fp, "\
+ %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
+ fprintf (fp, "\
+ %6.2g max. distance for merging two simplicial facets\n\
+ %6.2g max. roundoff error for arithmetic operations\n\
+ %6.2g min. denominator for divisions\n\
+ zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
+ for (k=0; k < qh hull_dim; k++)
+ fprintf (fp, "%6.2e ", qh NEARzero[k]);
+ fprintf (fp, "\n\n");
+ for (i=0 ; i < qhstat next; )
+ qh_printstats (fp, i, &i);
+} /* printstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="printstatlevel">-</a>
+
+ qh_printstatlevel( fp, id )
+ print level information for a statistic
+
+ notes:
+ nop if id >= ZEND, printed, or same as initial value
+*/
+void qh_printstatlevel (FILE *fp, int id, int start) {
+#define NULLfield " "
+
+ if (id >= ZEND || qhstat printed[id])
+ return;
+ if (qhstat type[id] == zdoc) {
+ fprintf (fp, "%s\n", qhstat doc[id]);
+ return;
+ }
+ start= 0; /* not used */
+ if (qh_nostatistic(id) || !qhstat doc[id])
+ return;
+ qhstat printed[id]= True;
+ if (qhstat count[id] != -1
+ && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
+ fprintf (fp, " *0 cnt*");
+ else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
+ fprintf (fp, "%7.2g", qhstat stats[id].r);
+ else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
+ fprintf (fp, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
+ else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
+ fprintf (fp, "%7d", qhstat stats[id].i);
+ else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
+ fprintf (fp, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
+ fprintf (fp, " %s\n", qhstat doc[id]);
+} /* printstatlevel */
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="printstats">-</a>
+
+ qh_printstats( fp, index, nextindex )
+ print statistics for a zdoc group
+
+ returns:
+ next zdoc if non-null
+*/
+void qh_printstats (FILE *fp, int index, int *nextindex) {
+ int j, nexti;
+
+ if (qh_newstats (index, &nexti)) {
+ fprintf (fp, "\n");
+ for (j=index; j<nexti; j++)
+ qh_printstatlevel (fp, qhstat id[j], 0);
+ }
+ if (nextindex)
+ *nextindex= nexti;
+} /* printstats */
+
+#if qh_KEEPstatistics
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="stddev">-</a>
+
+ qh_stddev( num, tot, tot2, ave )
+ compute the standard deviation and average from statistics
+
+ tot2 is the sum of the squares
+ notes:
+ computes r.m.s.:
+ (x-ave)^2
+ == x^2 - 2x tot/num + (tot/num)^2
+ == tot2 - 2 tot tot/num + tot tot/num
+ == tot2 - tot ave
+*/
+realT qh_stddev (int num, realT tot, realT tot2, realT *ave) {
+ realT stddev;
+
+ *ave= tot/num;
+ stddev= sqrt (tot2/num - *ave * *ave);
+ return stddev;
+} /* stddev */
+
+#endif /* qh_KEEPstatistics */
+
+#if !qh_KEEPstatistics
+void qh_collectstatistics (void) {}
+void qh_printallstatistics (FILE *fp, char *string) {};
+void qh_printstatistics (FILE *fp, char *string) {}
+#endif
+
diff --git a/extern/qhull/src/stat.h b/extern/qhull/src/stat.h
new file mode 100644
index 00000000000..1dae54ed21d
--- /dev/null
+++ b/extern/qhull/src/stat.h
@@ -0,0 +1,520 @@
+ /*<html><pre> -<a href="qh-stat.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ stat.h
+ contains all statistics that are collected for qhull
+
+ see qh-stat.htm and stat.c
+
+ copyright (c) 1993-2002, The Geometry Center
+
+ recompile qhull if you change this file
+
+ Integer statistics are Z* while real statistics are W*.
+
+ define maydebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="KEEPstatistics">-</a>
+
+ qh_KEEPstatistics
+ 0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="statistics">-</a>
+
+ Zxxx for integers, Wxxx for reals
+
+ notes:
+ be sure that all statistics are defined in stat.c
+ otherwise initialization may core dump
+ can pick up all statistics by:
+ grep '[zw].*_[(][ZW]' *.c >z.x
+ remove trailers with query">-</a>
+ remove leaders with query-replace-regexp [ ^I]+ (
+*/
+#if qh_KEEPstatistics
+enum statistics { /* alphabetical after Z/W */
+ Zacoplanar,
+ Wacoplanarmax,
+ Wacoplanartot,
+ Zangle,
+ Wangle,
+ Wanglemax,
+ Wanglemin,
+ Zangletests,
+ Wareatot,
+ Wareamax,
+ Wareamin,
+ Zavoidold,
+ Wavoidoldmax,
+ Wavoidoldtot,
+ Zback0,
+ Zbestcentrum,
+ Zbestdist,
+ Zcentrumtests,
+ Zcheckpart,
+ Zcomputefurthest,
+ Zconcave,
+ Wconcavemax,
+ Wconcavetot,
+ Zconcaveridges,
+ Zconcaveridge,
+ Zcoplanar,
+ Wcoplanarmax,
+ Wcoplanartot,
+ Zcoplanarangle,
+ Zcoplanarcentrum,
+ Zcoplanarhorizon,
+ Zcoplanarinside,
+ Zcoplanarpart,
+ Zcoplanarridges,
+ Wcpu,
+ Zcyclefacetmax,
+ Zcyclefacettot,
+ Zcyclehorizon,
+ Zcyclevertex,
+ Zdegen,
+ Wdegenmax,
+ Wdegentot,
+ Zdegenvertex,
+ Zdelfacetdup,
+ Zdelridge,
+ Zdelvertextot,
+ Zdelvertexmax,
+ Zdetsimplex,
+ Zdistcheck,
+ Zdistconvex,
+ Zdistgood,
+ Zdistio,
+ Zdistplane,
+ Zdiststat,
+ Zdistvertex,
+ Zdistzero,
+ Zdoc1,
+ Zdoc2,
+ Zdoc3,
+ Zdoc4,
+ Zdoc5,
+ Zdoc6,
+ Zdoc7,
+ Zdoc8,
+ Zdoc9,
+ Zdoc10,
+ Zdoc11,
+ Zdoc12,
+ Zdropdegen,
+ Zdropneighbor,
+ Zdupflip,
+ Zduplicate,
+ Wduplicatemax,
+ Wduplicatetot,
+ Zdupridge,
+ Zdupsame,
+ Zflipped,
+ Wflippedmax,
+ Wflippedtot,
+ Zflippedfacets,
+ Zfindbest,
+ Zfindbestmax,
+ Zfindbesttot,
+ Zfindcoplanar,
+ Zfindfail,
+ Zfindhorizon,
+ Zfindhorizonmax,
+ Zfindhorizontot,
+ Zfindjump,
+ Zfindnew,
+ Zfindnewmax,
+ Zfindnewtot,
+ Zfindnewjump,
+ Zfindnewsharp,
+ Zgauss0,
+ Zgoodfacet,
+ Zhashlookup,
+ Zhashridge,
+ Zhashridgetest,
+ Zhashtests,
+ Zinsidevisible,
+ Zintersect,
+ Zintersectfail,
+ Zintersectmax,
+ Zintersectnum,
+ Zintersecttot,
+ Zmaxneighbors,
+ Wmaxout,
+ Wmaxoutside,
+ Zmaxridges,
+ Zmaxvertex,
+ Zmaxvertices,
+ Zmaxvneighbors,
+ Zmemfacets,
+ Zmempoints,
+ Zmemridges,
+ Zmemvertices,
+ Zmergeflipdup,
+ Zmergehorizon,
+ Zmergeinittot,
+ Zmergeinitmax,
+ Zmergeinittot2,
+ Zmergeintohorizon,
+ Zmergenew,
+ Zmergesettot,
+ Zmergesetmax,
+ Zmergesettot2,
+ Zmergesimplex,
+ Zmergevertex,
+ Wmindenom,
+ Wminvertex,
+ Zminnorm,
+ Zmultiridge,
+ Znearlysingular,
+ Zneighbor,
+ Wnewbalance,
+ Wnewbalance2,
+ Znewfacettot,
+ Znewfacetmax,
+ Znewvertex,
+ Wnewvertex,
+ Wnewvertexmax,
+ Znoarea,
+ Znonsimplicial,
+ Znowsimplicial,
+ Znotgood,
+ Znotgoodnew,
+ Znotmax,
+ Znumfacets,
+ Znummergemax,
+ Znummergetot,
+ Znumneighbors,
+ Znumridges,
+ Znumvertices,
+ Znumvisibility,
+ Znumvneighbors,
+ Zonehorizon,
+ Zpartangle,
+ Zpartcoplanar,
+ Zpartflip,
+ Zparthorizon,
+ Zpartinside,
+ Zpartition,
+ Zpartitionall,
+ Zpartnear,
+ Zpbalance,
+ Wpbalance,
+ Wpbalance2,
+ Zpostfacets,
+ Zpremergetot,
+ Zprocessed,
+ Zremvertex,
+ Zremvertexdel,
+ Zrenameall,
+ Zrenamepinch,
+ Zrenameshare,
+ Zretry,
+ Wretrymax,
+ Zridge,
+ Wridge,
+ Wridgemax,
+ Zridge0,
+ Wridge0,
+ Wridge0max,
+ Zridgemid,
+ Wridgemid,
+ Wridgemidmax,
+ Zridgeok,
+ Wridgeok,
+ Wridgeokmax,
+ Zsearchpoints,
+ Zsetplane,
+ Ztestvneighbor,
+ Ztotcheck,
+ Ztothorizon,
+ Ztotmerge,
+ Ztotpartcoplanar,
+ Ztotpartition,
+ Ztotridges,
+ Ztotvertices,
+ Ztotvisible,
+ Ztricoplanar,
+ Ztricoplanarmax,
+ Ztricoplanartot,
+ Ztridegen,
+ Ztrimirror,
+ Ztrinull,
+ Wvertexmax,
+ Wvertexmin,
+ Zvertexridge,
+ Zvertexridgetot,
+ Zvertexridgemax,
+ Zvertices,
+ Zvisfacettot,
+ Zvisfacetmax,
+ Zvisvertextot,
+ Zvisvertexmax,
+ Zwidefacet,
+ Zwidevertices,
+ ZEND};
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="ZZstat">-</a>
+
+ Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+ notes:
+ be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum statistics { /* for zzdef etc. macros */
+ Zback0,
+ Zbestdist,
+ Zcentrumtests,
+ Zcheckpart,
+ Zconcaveridges,
+ Zcoplanarhorizon,
+ Zcoplanarpart,
+ Zcoplanarridges,
+ Zcyclefacettot,
+ Zcyclehorizon,
+ Zdelvertextot,
+ Zdistcheck,
+ Zdistconvex,
+ Zdistzero,
+ Zdoc1,
+ Zdoc2,
+ Zdoc3,
+ Zdoc11,
+ Zflippedfacets,
+ Zgauss0,
+ Zminnorm,
+ Zmultiridge,
+ Znearlysingular,
+ Wnewvertexmax,
+ Znumvisibility,
+ Zpartcoplanar,
+ Zpartition,
+ Zpartitionall,
+ Zprocessed,
+ Zretry,
+ Zridge,
+ Wridge,
+ Wridgemax,
+ Zridge0,
+ Wridge0,
+ Wridge0max,
+ Zridgemid,
+ Wridgemid,
+ Wridgemidmax,
+ Zridgeok,
+ Wridgeok,
+ Wridgeokmax,
+ Zsetplane,
+ Ztotmerge,
+ ZEND};
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >-------------------------------</a><a name="ztype">-</a>
+
+ ztype
+ the type of a statistic sets its initial value.
+
+ notes:
+ The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="MAYdebugx">-</a>
+
+ MAYdebugx
+ define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zdef_">-</a>
+
+ zzdef_, zdef_( type, name, doc, -1)
+ define a statistic (assumes 'qhstat.next= 0;')
+
+ zdef_( type, name, doc, count)
+ define an averaged statistic
+ printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zinc_">-</a>
+
+ zzinc_( name ), zinc_( name)
+ increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zadd_">-</a>
+
+ zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+ add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zval_">-</a>
+
+ zzval_( name ), zval_( name ), wwval_( name )
+ set or return value of a statistic
+*/
+#define zzval_(id) ((qhstat stats[id]).i)
+#define wwval_(id) ((qhstat stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qhstat stats[id]).i)
+#define wval_(id) ((qhstat stats[id]).r)
+#else
+#define zval_(id) qhstat tempi
+#define wval_(id) qhstat tempr
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zmax_">-</a>
+
+ zmax_( id, val ), wmax_( id, value )
+ maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="zmin_">-</a>
+
+ zmin_( id, val ), wmin_( id, value )
+ minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat.h types ==============*/
+
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="intrealT">-</a>
+
+ intrealT
+ union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT; /* union of int and realT */
+union intrealT {
+ int i;
+ realT r;
+};
+
+/*-<a href="qh-stat.htm#TOC"
+ >--------------------------------</a><a name="qhstat">-</a>
+
+ qhstat
+ global data structure for statistics
+
+ notes:
+ access to qh_qhstat is via the "qhstat" macro. There are two choices
+ qh_QHpointer = 1 access globals via a pointer
+ enables qh_saveqhull() and qh_restoreqhull()
+ = 0 qh_qhstat is a static data structure
+ only one instance of qhull() can be active at a time
+ default value
+ qh_QHpointer is defined in qhull.h
+
+ allocated in stat.c
+*/
+typedef struct qhstatT qhstatT;
+#if qh_QHpointer
+#define qhstat qh_qhstat->
+extern qhstatT *qh_qhstat;
+#else
+#define qhstat qh_qhstat.
+extern qhstatT qh_qhstat;
+#endif
+struct qhstatT {
+ intrealT stats[ZEND]; /* integer and real statistics */
+ unsigned char id[ZEND+10]; /* id's in print order */
+ char *doc[ZEND]; /* array of documentation strings */
+ short int count[ZEND]; /* -1 if none, else index of count to use */
+ char type[ZEND]; /* type, see ztypes above */
+ char printed[ZEND]; /* true, if statistic has been printed */
+ intrealT init[ZTYPEend]; /* initial values by types, set initstatistics */
+
+ int next; /* next index for zdef_ */
+ int precision; /* index for precision problems */
+ int vridges; /* index for Voronoi ridges */
+ int tempi;
+ realT tempr;
+};
+
+/*========== function prototypes ===========*/
+
+void qh_allstatA(void);
+void qh_allstatB(void);
+void qh_allstatC(void);
+void qh_allstatD(void);
+void qh_allstatE(void);
+void qh_allstatE2(void);
+void qh_allstatF(void);
+void qh_allstatG(void);
+void qh_allstatH(void);
+void qh_allstatI(void);
+void qh_allstatistics (void);
+void qh_collectstatistics (void);
+void qh_freestatistics (void);
+void qh_initstatistics (void);
+boolT qh_newstats (int index, int *nextindex);
+boolT qh_nostatistic (int i);
+void qh_printallstatistics (FILE *fp, char *string);
+void qh_printstatistics (FILE *fp, char *string);
+void qh_printstatlevel (FILE *fp, int id, int start);
+void qh_printstats (FILE *fp, int index, int *nextindex);
+realT qh_stddev (int num, realT tot, realT tot2, realT *ave);
+
+#endif /* qhDEFstat */
diff --git a/extern/qhull/src/unix.c b/extern/qhull/src/unix.c
new file mode 100644
index 00000000000..5ec5feab16c
--- /dev/null
+++ b/extern/qhull/src/unix.c
@@ -0,0 +1,376 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ unix.c
+ command line interface to qhull
+ includes SIOUX interface for Macintoshes
+
+ see qh-qhull.htm
+
+ copyright (c) 1993-2002, The Geometry Center
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include <SIOUX.h>
+#include <Files.h>
+#include <console.h>
+#include <Desk.h>
+
+#elif __cplusplus
+extern "C" {
+ int isatty (int);
+}
+
+#elif _MSC_VER
+#include <io.h>
+#define isatty _isatty
+
+#else
+int isatty (int); /* returns 1 if stdin is a tty
+ if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt">-</a>
+
+ qh_prompt
+ long prompt for qhull
+
+ see:
+ concise prompt below
+*/
+char qh_prompta[]= "\n\
+qhull- compute convex hulls and related structures.\n\
+ http://www.geom.umn.edu/software/qhull %s\n\
+\n\
+input (stdin):\n\
+ first lines: dimension and number of points (or vice-versa).\n\
+ other lines: point coordinates, best if one point per line\n\
+ comments: start with a non-numeric character\n\
+ halfspaces: use dim plus one and put offset after coefficients.\n\
+ May be preceeded by a single interior point ('H').\n\
+\n\
+options:\n\
+ d - Delaunay triangulation by lifting points to a paraboloid\n\
+ d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
+ v - Voronoi diagram (dual of the Delaunay triangulation)\n\
+ v Qu - furthest-site Voronoi diagram\n\
+ Hn,n,... - halfspace intersection about point [n,n,0,...]\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Qc - keep coplanar points with nearest facet\n\
+ Qi - keep interior points with nearest facet\n\
+\n\
+Qhull control options:\n\
+ Qbk:n - scale coord k so that low bound is n\n\
+ QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
+ QbB - scale input to unit cube centered at the origin\n\
+ Qbb - scale last coordinate to [0,m] for Delaunay triangulations\n\
+ Qbk:0Bk:0 - remove k-th coordinate from input\n\
+ QJn - randomly joggle input in range [-n,n]\n\
+ QRn - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
+%s%s%s%s"; /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+ Qf - partition point to furthest outside facet\n\
+ Qg - only build good facets (needs 'QGn', 'QVn', or 'PdD')\n\
+ Qm - only process points that would increase max_outside\n\
+ Qr - process random outside points instead of furthest ones\n\
+ Qs - search all points for the initial simplex\n\
+ Qu - for 'd' or 'v', compute upper hull without point at-infinity\n\
+ returns furthest-site Delaunay triangulation\n\
+ Qv - test vertex neighbors for convexity\n\
+ Qx - exact pre-merges (skips coplanar and angle-coplanar facets)\n\
+ Qz - add point-at-infinity to Delaunay triangulation\n\
+ QGn - good facet if visible from point n, -n for not visible\n\
+ QVn - good facet if it includes point n, -n if not\n\
+ Q0 - turn off default premerge with 'C-0'/'Qx'\n\
+ Q1 - sort merges by type instead of angle\n\
+ Q2 - merge all non-convex at once instead of independent sets\n\
+ Q3 - do not merge redundant vertices\n\
+ Q4 - avoid old->new merges\n\
+ Q5 - do not correct outer planes at end of qhull\n\
+ Q6 - do not pre-merge concave or coplanar facets\n\
+ Q7 - depth-first processing instead of breadth-first\n\
+ Q8 - do not process near-inside points\n\
+ Q9 - process furthest of furthest points\n\
+ Q10 - no special processing for narrow distributions\n\
+ Q11 - copy normals and recompute centrums for tricoplanar facets\n\
+\n\
+";
+char qh_promptc[]= "\
+Topts- Trace options:\n\
+ T4 - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+ Tc - check frequently during execution\n\
+ Ts - print statistics\n\
+ Tv - verify result: structure, convexity, and point inclusion\n\
+ Tz - send all output to stdout\n\
+ TFn - report summary when n or more facets created\n\
+ TI file - input data from file, no spaces or single quotes\n\
+ TO file - output results to file, may be enclosed in single quotes\n\
+ TPn - turn on tracing when point n added to hull\n\
+ TMn - turn on tracing at merge n\n\
+ TWn - trace merge facets when width > n\n\
+ TRn - rerun qhull n times. Use with 'QJn'\n\
+ TVn - stop qhull after adding point n, -n for before (see TCn)\n\
+ TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+ Cn - radius of centrum (roundoff added). Merge facets if non-convex\n\
+ An - cosine of maximum angle. Merge facets if cosine > n or non-convex\n\
+ C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+ En - max roundoff error for distance computation\n\
+ Rn - randomly perturb computations by a factor of [1-n,1+n]\n\
+ Vn - min distance above plane for a visible facet (default 3C-n or En)\n\
+ Un - max distance below plane for a new, coplanar point (default Vn)\n\
+ Wn - min facet width for outside point (before roundoff, default 2Vn)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+ f - facet dump\n\
+ G - Geomview output (see below)\n\
+ i - vertices incident to each facet\n\
+ m - Mathematica output (2-d and 3-d)\n\
+ o - OFF format (dim, points and facets; Voronoi regions)\n\
+ n - normals with offsets\n\
+ p - vertex coordinates or Voronoi vertices (coplanar points if 'Qc')\n\
+ s - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+ Fa - area for each facet\n\
+ FA - compute total area and volume for option 's'\n\
+ Fc - count plus coplanar points for each facet\n\
+ use 'Qc' (default) for coplanar and 'Qi' for interior\n\
+ FC - centrum or Voronoi center for each facet\n\
+ Fd - use cdd format for input (homogeneous with offset first)\n\
+ FD - use cdd format for numeric output (offset first)\n\
+ FF - facet dump without ridges\n\
+ Fi - inner plane for each facet\n\
+ for 'v', separating hyperplanes for bounded Voronoi regions\n\
+ FI - ID of each facet\n\
+ Fm - merge count for each facet (511 max)\n\
+ Fn - count plus neighboring facets for each facet\n\
+ FN - count plus neighboring facets for each point\n\
+ Fo - outer plane (or max_outside) for each facet\n\
+ for 'v', separating hyperplanes for unbounded Voronoi regions\n\
+ FO - options and precision constants\n\
+ Fp - dim, count, and intersection coordinates (halfspace only)\n\
+ FP - nearest vertex and distance for each coplanar point\n\
+ FQ - command used for qhull\n\
+ Fs - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+ output: #vertices, #facets, #coplanars, #nonsimplicial\n\
+ #real (2), max outer plane, min vertex\n\
+ FS - sizes: #int (0)\n\
+ #real(2) tot area, tot volume\n\
+ Ft - triangulation with centrums for non-simplicial facets (OFF format)\n\
+ Fv - count plus vertices for each facet\n\
+ for 'v', Voronoi diagram as Voronoi vertices for pairs of sites\n\
+ FV - average of vertices (a feasible point for 'H')\n\
+ Fx - extreme points (in order for 2-d)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d, 3-d, and 4-d; 2-d Voronoi)\n\
+ Ga - all points as dots\n\
+ Gp - coplanar points and vertices as radii\n\
+ Gv - vertices as spheres\n\
+ Gi - inner planes only\n\
+ Gn - no planes\n\
+ Go - outer planes only\n\
+ Gc - centrums\n\
+ Gh - hyperplane intersections\n\
+ Gr - ridges\n\
+ GDn - drop dimension n in 3-d and 4-d output\n\
+ Gt - for 3-d 'd', transparent outer ridges\n\
+\n\
+Print options:\n\
+ PAn - keep n largest facets by area\n\
+ Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+ PDk:n - drop facet if normal[k] >= n\n\
+ Pg - print good facets (needs 'QGn' or 'QVn')\n\
+ PFn - keep facets whose area is at least n\n\
+ PG - print neighbors of good facets\n\
+ PMn - keep n facets with most merges\n\
+ Po - force output. If error, output neighborhood of facet\n\
+ Pp - do not report precision problems\n\
+\n\
+ . - list of all options\n\
+ - - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt2">-</a>
+
+ qh_prompt2
+ synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qhull- compute convex hulls and related structures. %s\n\
+ input (stdin): dimension, n, point coordinates\n\
+ comments start with a non-numeric character\n\
+ halfspace: use dim+1 and put offsets after coefficients\n\
+\n\
+options (qh-quick.htm):\n\
+ d - Delaunay triangulation by lifting points to a paraboloid\n\
+ d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
+ v - Voronoi diagram as the dual of the Delaunay triangulation\n\
+ v Qu - furthest-site Voronoi diagram\n\
+ H1,1 - Halfspace intersection about [1,1,0,...] via polar duality\n\
+ Qt - triangulated output\n\
+ QJ - joggled input instead of merged facets\n\
+ Tv - verify result: structure, convexity, and point inclusion\n\
+ . - concise list of all options\n\
+ - - one-line description of all options\n\
+\n\
+Output options (subset):\n\
+ s - summary of results (default)\n\
+ i - vertices incident to each facet\n\
+ n - normals with offsets\n\
+ p - vertex coordinates (if 'Qc', includes coplanar points)\n\
+ if 'v', Voronoi vertices\n\
+ Fp - halfspace intersections\n\
+ Fx - extreme points (convex hull vertices)\n\
+ FA - compute total area and volume\n\
+ o - OFF format (if 'v', outputs Voronoi regions)\n\
+ G - Geomview output (2-d, 3-d and 4-d)\n\
+ m - Mathematica output (2-d and 3-d)\n\
+ QVn - print facets that include point n, -n if not\n\
+ TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+ rbox c d D2 | qhull Qc s f Fx | more rbox 1000 s | qhull Tv s FA\n\
+ rbox 10 D2 | qhull d QJ s i TO result rbox 10 D2 | qhull v QJ p\n\
+ rbox 10 D2 | qhull d Qu QJ m rbox 10 D2 | qhull v Qu QJ o\n\
+ rbox c | qhull n rbox c | qhull FV n | qhull H Fp\n\
+ rbox d D12 | qhull QR0 FA rbox c D7 | qhull FA TF1000\n\
+ rbox y 1000 W0 | qhull rbox 10 | qhull v QJ o Fv\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="prompt3">-</a>
+
+ qh_prompt3
+ concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ delaunay voronoi Geomview Halfspace facet_dump\n\
+ incidences mathematica normals OFF_format points\n\
+ summary\n\
+\n\
+ Farea FArea-total Fcoplanars FCentrums Fd-cdd-in\n\
+ FD-cdd-out FF-dump-xridge Finner FIDs Fmerges\n\
+ Fneighbors FNeigh-vertex Fouter FOptions Fpoint-intersect\n\
+ FPoint_near FQhull Fsummary FSize Ftriangles\n\
+ Fvertices Fvoronoi FVertex-ave Fxtremes\n\
+\n\
+ Gvertices Gpoints Gall_points Gno_planes Ginner\n\
+ Gcentrums Ghyperplanes Gridges Gouter GDrop_dim\n\
+ Gtransparent\n\
+\n\
+ PArea-keep Pdrop d0:0D0 Pgood PFacet_area_keep\n\
+ PGood_neighbors PMerge-keep Poutput_forced Pprecision_not\n\
+\n\
+ QbBound 0:0.5 Qbk:0Bk:0_drop QbB-scale-box Qbb-scale-last Qcoplanar\n\
+ Qfurthest Qgood_only QGood_point Qinterior Qmax_out\n\
+ QJoggle Qrandom QRotate Qsearch_1st Qtriangulate\n\
+ QupperDelaunay QVertex_good Qvneighbors Qxact_merge Qzinfinite\n\
+\n\
+ Q0_no_premerge Q1_no_angle Q2_no_independ Q3_no_redundant Q4_no_old\n\
+ Q5_no_check_out Q6_no_concave Q7_depth_first Q8_no_near_in Q9_pick_furthest\n\
+ Q10_no_narrow Q11_trinormals\n\
+\n\
+ T4_trace Tcheck_often Tstatistics Tverify Tz_stdout\n\
+ TFacet_log TInput_file TPoint_trace TMerge_trace TOutput_file\n\
+ TRerun TWide_trace TVertex_stop TCone_stop\n\
+\n\
+ Angle_max Centrum_size Error_round Random_dist Visible_min\n\
+ Ucoplanar_max Wide_outside\n\
+";
+
+/*-<a href="qh-qhull.htm#TOC"
+ >-------------------------------</a><a name="main">-</a>
+
+ main( argc, argv )
+ processes the command line, calls qhull() to do the work, and exits
+
+ design:
+ initializes data structures
+ reads points
+ finishes initialization
+ computes convex hull and other structures
+ checks the result
+ writes the output
+ frees memory
+*/
+int main(int argc, char *argv[]) {
+ int curlong, totlong; /* used !qh_NOmem */
+ int exitcode, numpoints, dim;
+ coordT *points;
+ boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+ char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+ SIOUXSettings.showstatusline= false;
+ SIOUXSettings.tabspaces= 1;
+ SIOUXSettings.rows= 40;
+ if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0 /* w/o, SIOUX I/O is slow*/
+ || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+ || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+ fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+ argc= ccommand(&argv);
+#endif
+
+ if ((argc == 1) && isatty( 0 /*stdin*/)) {
+ fprintf(stdout, qh_prompt2, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompta, qh_VERSION, qh_DEFAULTbox,
+ qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+ exit(qh_ERRnone);
+ }
+ if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+ fprintf(stdout, qh_prompt3, qh_VERSION);
+ exit(qh_ERRnone);
+ }
+ qh_init_A (stdin, stdout, stderr, argc, argv); /* sets qh qhull_command */
+ exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+ if (!exitcode) {
+ qh_initflags (qh qhull_command);
+ points= qh_readpoints (&numpoints, &dim, &ismalloc);
+ qh_init_B (points, numpoints, dim, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ exitcode= qh_ERRnone;
+ }
+ qh NOerrexit= True; /* no more setjmp */
+#ifdef qh_NOmem
+ qh_freeqhull( True);
+#else
+ qh_freeqhull( False);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+#endif
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/user.c b/extern/qhull/src/user.c
new file mode 100644
index 00000000000..94b31aaf99f
--- /dev/null
+++ b/extern/qhull/src/user.c
@@ -0,0 +1,324 @@
+/*<html><pre> -<a href="qh-user.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ user.c
+ user redefinable functions
+
+ see README.txt see COPYING.txt for copyright information.
+
+ see qhull.h for data structures, macros, and user-callable functions.
+
+ see user_eg.c, unix.c, and qhull_interface.cpp for examples.
+
+ see user.h for user-definable constants
+
+ use qh_NOmem in mem.h to turn off memory management
+ use qh_NOmerge in user.h to turn off facet merging
+ set qh_KEEPstatistics in user.h to 0 to turn off statistics
+
+ This is unsupported software. You're welcome to make changes,
+ but you're on your own if something goes wrong. Use 'Tc' to
+ check frequently. Usually qhull will report an error if
+ a data structure becomes inconsistent. If so, it also reports
+ the last point added to the hull, e.g., 102. You can then trace
+ the execution of qhull with "T4P102".
+
+ Please report any errors that you fix to qhull@geom.umn.edu
+
+ call_qhull is a template for calling qhull from within your application
+
+ if you recompile and load this module, then user.o will not be loaded
+ from qhull.a
+
+ you can add additional quick allocation sizes in qh_user_memsizes
+
+ if the other functions here are redefined to not use qh_print...,
+ then io.o will not be loaded from qhull.a. See user_eg.c for an
+ example. We recommend keeping io.o for the extra debugging
+ information it supplies.
+*/
+
+#include "qhull_a.h"
+
+/*-<a href="qh-user.htm#TOC"
+ >-------------------------------</a><a name="call_qhull">-</a>
+
+ qh_call_qhull( void )
+ template for calling qhull from inside your program
+ remove #if 0, #endif to compile
+
+ returns:
+ exit code (see qh_ERR... in qhull.h)
+ all memory freed
+
+ notes:
+ This can be called any number of times.
+
+ see:
+ qh_call_qhull_once()
+
+*/
+#if 0
+{
+ int dim; /* dimension of points */
+ int numpoints; /* number of points */
+ coordT *points; /* array of coordinates for each point */
+ boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
+ char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
+ FILE *outfile= stdout; /* output from qh_produce_output()
+ use NULL to skip qh_produce_output() */
+ FILE *errfile= stderr; /* error messages from qhull code */
+ int exitcode; /* 0 if no error from qhull */
+ facetT *facet; /* set by FORALLfacets */
+ int curlong, totlong; /* memory remaining after qh_memfreeshort */
+
+ /* initialize dim, numpoints, points[], ismalloc here */
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode) { /* if no error */
+ /* 'qh facet_list' contains the convex hull */
+ FORALLfacets {
+ /* ... your code ... */
+ }
+ }
+ qh_freeqhull(!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong)
+ fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+}
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >-------------------------------</a><a name="new_qhull">-</a>
+
+ qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
+ build new qhull data structure and return exitcode (0 if no errors)
+
+ notes:
+ do not modify points until finished with results.
+ The qhull data structure contains pointers into the points array.
+ do not call qhull functions before qh_new_qhull().
+ The qhull data structure is not initialized until qh_new_qhull().
+
+ outfile may be null
+ qhull_cmd must start with "qhull "
+ projects points to a new point array for Delaunay triangulations ('d' and 'v')
+ transforms points into a new point array for halfspace intersection ('H')
+
+
+ To allow multiple, concurrent calls to qhull()
+ - set qh_QHpointer in user.h
+ - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
+ - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
+
+ see:
+ user_eg.c for an example
+*/
+int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
+ char *qhull_cmd, FILE *outfile, FILE *errfile) {
+ int exitcode, hulldim;
+ boolT new_ismalloc;
+ static boolT firstcall = True;
+ coordT *new_points;
+
+ if (firstcall) {
+ qh_meminit (errfile);
+ firstcall= False;
+ }
+ if (strncmp (qhull_cmd,"qhull ", 6)) {
+ fprintf (errfile, "qh_new_qhull: start qhull_cmd argument with \"qhull \"\n");
+ exit(1);
+ }
+ qh_initqhull_start (NULL, outfile, errfile);
+ trace1(( qh ferr, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
+ exitcode = setjmp (qh errexit);
+ if (!exitcode)
+ {
+ qh NOerrexit = False;
+ qh_initflags (qhull_cmd);
+ if (qh DELAUNAY)
+ qh PROJECTdelaunay= True;
+ if (qh HALFspace) {
+ /* points is an array of halfspaces,
+ the last coordinate of each halfspace is its offset */
+ hulldim= dim-1;
+ qh_setfeasible (hulldim);
+ new_points= qh_sethalfspace_all (dim, numpoints, points, qh feasible_point);
+ new_ismalloc= True;
+ if (ismalloc)
+ free (points);
+ }else {
+ hulldim= dim;
+ new_points= points;
+ new_ismalloc= ismalloc;
+ }
+ qh_init_B (new_points, numpoints, hulldim, new_ismalloc);
+ qh_qhull();
+ qh_check_output();
+ if (outfile)
+ qh_produce_output();
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points();
+ }
+ qh NOerrexit = True;
+ return exitcode;
+} /* new_qhull */
+
+/*-<a href="qh-user.htm#TOC"
+ >-------------------------------</a><a name="errexit">-</a>
+
+ qh_errexit( exitcode, facet, ridge )
+ report and exit from an error
+ report facet and ridge if non-NULL
+ reports useful information such as last point processed
+ set qh.FORCEoutput to print neighborhood of facet
+
+ see:
+ qh_errexit2() in qhull.c for printing 2 facets
+
+ design:
+ check for error within error processing
+ compute qh.hulltime
+ print facet and ridge (if any)
+ report commandString, options, qh.furthest_id
+ print summary and statistics (including precision statistics)
+ if qh_ERRsingular
+ print help text for singular data set
+ exit program via long jump (if defined) or exit()
+*/
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
+
+ if (qh ERREXITcalled) {
+ fprintf (qh ferr, "\nqhull error while processing previous error. Exit program\n");
+ exit(1);
+ }
+ qh ERREXITcalled= True;
+ if (!qh QHULLfinished)
+ qh hulltime= qh_CPUclock - qh hulltime;
+ qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
+ fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
+ fprintf(qh ferr, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
+ if (qh furthest_id >= 0) {
+ fprintf(qh ferr, "Last point added to hull was p%d.", qh furthest_id);
+ if (zzval_(Ztotmerge))
+ fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge));
+ if (qh QHULLfinished)
+ fprintf(qh ferr, "\nQhull has finished constructing the hull.");
+ else if (qh POSTmerging)
+ fprintf(qh ferr, "\nQhull has started post-merging.");
+ fprintf (qh ferr, "\n");
+ }
+ if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
+ qh_produce_output();
+ else {
+ if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
+ fprintf (qh ferr, "\nAt error exit:\n");
+ qh_printsummary (qh ferr);
+ if (qh PRINTstatistics) {
+ qh_collectstatistics();
+ qh_printstatistics(qh ferr, "at error exit");
+ qh_memstatistics (qh ferr);
+ }
+ }
+ if (qh PRINTprecision)
+ qh_printstats (qh ferr, qhstat precision, NULL);
+ }
+ if (!exitcode)
+ exitcode= qh_ERRqhull;
+ else if (exitcode == qh_ERRsingular)
+ qh_printhelp_singular(qh ferr);
+ else if (exitcode == qh_ERRprec && !qh PREmerge)
+ qh_printhelp_degenerate (qh ferr);
+ if (qh NOerrexit) {
+ fprintf (qh ferr, "qhull error while ending program. Exit program\n");
+ exit(1);
+ }
+ qh NOerrexit= True;
+ longjmp(qh errexit, exitcode);
+} /* errexit */
+
+
+/*-<a href="qh-user.htm#TOC"
+ >-------------------------------</a><a name="errprint">-</a>
+
+ qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
+ prints out the information of facets and ridges to fp
+ also prints neighbors and geomview output
+
+ notes:
+ except for string, any parameter may be NULL
+*/
+void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+ int i;
+
+ if (atfacet) {
+ fprintf(qh ferr, "%s FACET:\n", string);
+ qh_printfacet(qh ferr, atfacet);
+ }
+ if (otherfacet) {
+ fprintf(qh ferr, "%s OTHER FACET:\n", string);
+ qh_printfacet(qh ferr, otherfacet);
+ }
+ if (atridge) {
+ fprintf(qh ferr, "%s RIDGE:\n", string);
+ qh_printridge(qh ferr, atridge);
+ if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
+ qh_printfacet(qh ferr, atridge->top);
+ if (atridge->bottom
+ && atridge->bottom != atfacet && atridge->bottom != otherfacet)
+ qh_printfacet(qh ferr, atridge->bottom);
+ if (!atfacet)
+ atfacet= atridge->top;
+ if (!otherfacet)
+ otherfacet= otherfacet_(atridge, atfacet);
+ }
+ if (atvertex) {
+ fprintf(qh ferr, "%s VERTEX:\n", string);
+ qh_printvertex (qh ferr, atvertex);
+ }
+ if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
+ fprintf(qh ferr, "ERRONEOUS and NEIGHBORING FACETS to output\n");
+ for (i= 0; i < qh_PRINTEND; i++) /* use fout for geomview output */
+ qh_printneighborhood (qh fout, qh PRINTout[i], atfacet, otherfacet,
+ !qh_ALL);
+ }
+} /* errprint */
+
+
+/*-<a href="qh-user.htm#TOC"
+ >-------------------------------</a><a name="printfacetlist">-</a>
+
+ qh_printfacetlist( fp, facetlist, facets, printall )
+ print all fields for a facet list and/or set of facets to fp
+ if !printall,
+ only prints good facets
+
+ notes:
+ also prints all vertices
+*/
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
+ facetT *facet, **facetp;
+
+ qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+ FORALLfacet_(facetlist)
+ qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+ FOREACHfacet_(facets)
+ qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+ qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+} /* printfacetlist */
+
+
+/*-<a href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="user_memsizes">-</a>
+
+ qh_user_memsizes()
+ allocate up to 10 additional, quick allocation sizes
+
+ notes:
+ increase maximum number of allocations in qh_initqhull_mem()
+*/
+void qh_user_memsizes (void) {
+
+ /* qh_memsize (size); */
+} /* user_memsizes */
+
diff --git a/extern/qhull/src/user.h b/extern/qhull/src/user.h
new file mode 100644
index 00000000000..79558967a52
--- /dev/null
+++ b/extern/qhull/src/user.h
@@ -0,0 +1,762 @@
+/*<html><pre> -<a href="qh-user.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ user.h
+ user redefinable constants
+
+ see qh-user.htm. see COPYING for copyright information.
+
+ before reading any code, review qhull.h for data structure definitions and
+ the "qh" macro.
+*/
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/*============= data types and configuration macros ==========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="realT">-</a>
+
+ realT
+ set the size of floating point numbers
+
+ qh_REALdigits
+ maximimum number of significant digits
+
+ qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+ format strings for printf
+
+ qh_REALmax, qh_REALmin
+ maximum and minimum (near zero) values
+
+ qh_REALepsilon
+ machine roundoff. Maximum roundoff error for addition and multiplication.
+
+ notes:
+ Select whether to store floating point numbers in single precision (float)
+ or double precision (double).
+
+ Use 'float' to save about 8% in time and 25% in space. This is particularly
+ help if high-d where convex hulls are space limited. Using 'float' also
+ reduces the printed size of Qhull's output since numbers have 8 digits of
+ precision.
+
+ Use 'double' when greater arithmetic precision is needed. This is needed
+ for Delaunay triangulations and Voronoi diagrams when you are not merging
+ facets.
+
+ If 'double' gives insufficient precision, your data probably includes
+ degeneracies. If so you should use facet merging (done by default)
+ or exact arithmetic (see imprecision section of manual, qh-impre.htm).
+ You may also use option 'Po' to force output despite precision errors.
+
+ You may use 'long double', but many format statements need to be changed
+ and you may need a 'long double' square root routine. S. Grundmann
+ (sg@eeiwzb.et.tu-dresden.de) has done this. He reports that the code runs
+ much slower with little gain in precision.
+
+ WARNING: on some machines, int f(){realT a= REALmax;return (a == REALmax);}
+ returns False. Use (a > REALmax/2) instead of (a == REALmax).
+
+ REALfloat = 1 all numbers are 'float' type
+ = 0 all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8 /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16 /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="CPUclock">-</a>
+
+ qh_CPUclock
+ define the clock() function for reporting the total time spent by Qhull
+ returns CPU ticks as a 'long int'
+ qh_CPUclock is only used for reporting the total time spent by Qhull
+
+ qh_SECticks
+ the number of clock ticks per second
+
+ notes:
+ looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+ to define a custom clock, set qh_CLOCKtype to 0
+
+ if your system does not use clock() to return CPU ticks, replace
+ qh_CPUclock with the corresponding function. It is converted
+ to unsigned long to prevent wrap-around during long runs.
+
+
+ Set qh_CLOCKtype to
+
+ 1 for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+ Note: may fail if more than 1 hour elapsed time
+
+ 2 use qh_clock() with POSIX times() (see global.c)
+*/
+#define qh_CLOCKtype 1 /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined (CLOCKS_PER_SECOND)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined (CLOCKS_PER_SEC)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined (CLK_TCK)
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock qh_clock() /* return CPU clock */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="RANDOM">-</a>
+
+ qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+ define random number generator
+
+ qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
+ qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+ Set qh_RANDOMtype (default 5) to:
+ 1 for random() with 31 bits (UCB)
+ 2 for rand() with RAND_MAX or 15 bits (system 5)
+ 3 for rand() with 31 bits (Sun)
+ 4 for lrand48() with 31 bits (Solaris)
+ 5 for qh_rand() with 31 bits (included with Qhull)
+
+ notes:
+ Random numbers are used by rbox to generate point sets. Random
+ numbers are used by Qhull to rotate the input ('QRn' option),
+ simulate a randomized algorithm ('Qr' option), and to simulate
+ roundoff errors ('Rn' option).
+
+ Random number generators differ between systems. Most systems provide
+ rand() but the period varies. The period of rand() is not critical
+ since qhull does not normally use random numbers.
+
+ The default generator is Park & Miller's minimal standard random
+ number generator [CACM 31:1195 '88]. It is included with Qhull.
+
+ If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
+ output will likely be invisible.
+*/
+#define qh_RANDOMtype 5 /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767) /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, Sun */
+#define qh_RANDOMint rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)
+#define qh_RANDOMmax ((realT)2147483646UL) /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand()
+#define qh_RANDOMseed_(seed) qh_srand(seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="ORIENTclock">-</a>
+
+ qh_ORIENTclock
+ 0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0
+
+
+/*========= performance related constants =========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="HASHfactor">-</a>
+
+ qh_HASHfactor
+ total hash slots / used hash slots. Must be at least 1.1.
+
+ notes:
+ =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="VERIFYdirect">-</a>
+
+ qh_VERIFYdirect
+ with 'Tv' verify all points against all facets if op count is smaller
+
+ notes:
+ if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INITIALsearch">-</a>
+
+ qh_INITIALsearch
+ if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INITIALmax">-</a>
+
+ qh_INITIALmax
+ if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+
+ notes:
+ from points with non-zero determinants
+ use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEdefault">-</a>
+
+ qh_JOGGLEdefault
+ default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+ notes:
+ rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+ rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+ rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+ rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+ rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+ rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+ rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+ rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+ rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+ the later have about 20 points per facet, each of which may interfere
+
+ pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEincrease">-</a>
+
+ qh_JOGGLEincrease
+ factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEretry">-</a>
+
+ qh_JOGGLEretry
+ if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+ notes:
+ try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEagain">-</a>
+
+ qh_JOGGLEagain
+ every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+ notes:
+ 1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEmaxincrease">-</a>
+
+ qh_JOGGLEmaxincrease
+ maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+ relative to qh.MAXwidth
+
+ notes:
+ qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="JOGGLEmaxretry">-</a>
+
+ qh_JOGGLEmaxretry
+ stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 100
+
+/*========= memory constants =========*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMalign">-</a>
+
+ qh_MEMalign
+ memory alignment for qh_meminitbuffers() in global.c
+
+ notes:
+ to avoid bus errors, memory allocation must consider alignment requirements.
+ malloc() automatically takes care of alignment. Since mem.c manages
+ its own memory, we need to explicitly specify alignment in
+ qh_meminitbuffers().
+
+ A safe choice is sizeof(double). sizeof(float) may be used if doubles
+ do not occur in data structures and pointers are the same size. Be careful
+ of machines (e.g., DEC Alpha) with large pointers.
+
+ If using gcc, best alignment is
+ #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMbufsize">-</a>
+
+ qh_MEMbufsize
+ size of additional memory buffers
+
+ notes:
+ used for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMbufsize 0x10000 /* allocate 64K memory buffers */
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MEMinitbuf">-</a>
+
+ qh_MEMinitbuf
+ size of initial memory buffer
+
+ notes:
+ use for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMinitbuf 0x20000 /* initially allocate 128K buffer */
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="INFINITE">-</a>
+
+ qh_INFINITE
+ on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE -10.101
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DEFAULTbox">-</a>
+
+ qh_DEFAULTbox
+ default box size (Geomview expects 0.5)
+*/
+#define qh_DEFAULTbox 0.5
+
+/*======= conditional compilation ============================*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="compiler">-</a>
+
+ __cplusplus
+ defined by C++ compilers
+
+ __MSC_VER
+ defined by Microsoft Visual C++
+
+ __MWERKS__ && __POWERPC__
+ defined by Metrowerks when compiling for the Power Macintosh
+
+ __STDC__
+ defined for strict ANSI C
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="COMPUTEfurthest">-</a>
+
+ qh_COMPUTEfurthest
+ compute furthest distance to an outside point instead of storing it with the facet
+ =1 to compute furthest
+
+ notes:
+ computing furthest saves memory but costs time
+ about 40% more distance tests for partitioning
+ removes facet->furthestdist
+*/
+#define qh_COMPUTEfurthest 0
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="KEEPstatistics">-</a>
+
+ qh_KEEPstatistics
+ =0 removes most of statistic gathering and reporting
+
+ notes:
+ if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXoutside">-</a>
+
+ qh_MAXoutside
+ record outer plane for each facet
+ =1 to record facet->maxoutside
+
+ notes:
+ this takes a realT per facet and slightly slows down qhull
+ it produces better outer planes for geomview output
+*/
+#define qh_MAXoutside 1
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="NOmerge">-</a>
+
+ qh_NOmerge
+ disables facet merging if defined
+
+ notes:
+ This saves about 10% space.
+
+ Unless 'Q0'
+ qh_NOmerge sets 'QJ' to avoid precision errors
+
+ #define qh_NOmerge
+
+ see:
+ <a href="mem.h#NOmem">qh_NOmem</a> in mem.c
+
+ see user.c/user_eg.c for removing io.o
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="NOtrace">-</a>
+
+ qh_NOtrace
+ no tracing if defined
+
+ notes:
+ This saves about 5% space.
+
+ #define qh_NOtrace
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="QHpointer">-</a>
+
+ qh_QHpointer
+ access global data with pointer or static structure
+
+ qh_QHpointer = 1 access globals via a pointer to allocated memory
+ enables qh_saveqhull() and qh_restoreqhull()
+ costs about 8% in time and 2% in space
+
+ = 0 qh_qh and qh_qhstat are static data structures
+ only one instance of qhull() can be active at a time
+ default value
+
+ notes:
+ all global variables for qhull are in qh, qhmem, and qhstat
+ qh is defined in qhull.h
+ qhmem is defined in mem.h
+ qhstat is defined in stat.h
+
+ see:
+ user_eg.c for an example
+*/
+#define qh_QHpointer 0
+#if 0 /* sample code */
+ qhT *oldqhA, *oldqhB;
+
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ /* use results from first call to qh_new_qhull */
+ oldqhA= qh_save_qhull();
+ exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
+ flags, outfile, errfile);
+ /* use results from second call to qh_new_qhull */
+ oldqhB= qh_save_qhull();
+ qh_restore_qhull (&oldqhA);
+ /* use results from first call to qh_new_qhull */
+ qh_freeqhull (qh_ALL); /* frees all memory used by first call */
+ qh_restore_qhull (&oldqhB);
+ /* use results from second call to qh_new_qhull */
+ qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
+ qh_memfreeshort (&curlong, &totlong); /* frees short memory and memory allocator */
+#endif
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="QUICKhelp">-</a>
+
+ qh_QUICKhelp
+ =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp 0
+
+/* ============ -merge constants- ====================
+
+ These constants effect facet merging. You probably will not need
+ to modify these. They effect the performance of facet merging.
+*/
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DIMmergeVertex">-</a>
+
+ qh_DIMmergeVertex
+ max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DIMreduceBuild">-</a>
+
+ qh_DIMreduceBuild
+ max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="BESTcentrum">-</a>
+
+ qh_BESTcentrum
+ if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+ else, qh_findbestneighbor() tests all vertices (much better merges)
+
+ qh_BESTcentrum2
+ if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="BESTnonconvex">-</a>
+
+ qh_BESTnonconvex
+ if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+
+ notes:
+ It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnewmerges">-</a>
+
+ qh_MAXnewmerges
+ if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+
+ notes:
+ It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnewcentrum">-</a>
+
+ qh_MAXnewcentrum
+ if <= dim+n vertices (n approximates the number of merges),
+ reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+
+ notes:
+ needed to reduce cost and because centrums may move too much if
+ many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="COPLANARratio">-</a>
+
+ qh_COPLANARratio
+ for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+ notes:
+ for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="DISToutside">-</a>
+
+ qh_DISToutside
+ When is a point clearly outside of a facet?
+ Stops search in qh_findbestnew or qh_partitionall
+ qh_findbest uses qh.MINoutside since since it is only called if no merges.
+
+ notes:
+ 'Qf' always searches for best facet
+ if !qh.MERGING, same as qh.MINoutside.
+ if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+ [Note: Zdelvertextot occurs normally with interior points]
+ RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+ When there is a sharp edge, need to move points to a
+ clearly good facet; otherwise may be lost in another partitioning.
+ if too big then O(n^2) behavior for partitioning in cone
+ if very small then important points not processed
+ Needed in qh_partitionall for
+ RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+ Needed in qh_findbestnew for many instances of
+ RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+ fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="RATIOnearinside">-</a>
+
+ qh_RATIOnearinside
+ ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+ qh_check_maxout().
+
+ notes:
+ This is overkill since do not know the correct value.
+ It effects whether 'Qc' reports all coplanar points
+ Not used for 'd' since non-extreme points are coplanar
+*/
+#define qh_RATIOnearinside 5
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="SEARCHdist">-</a>
+
+ qh_SEARCHdist
+ When is a facet coplanar with the best facet?
+ qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+ (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="USEfindbestnew">-</a>
+
+ qh_USEfindbestnew
+ Always use qh_findbestnew for qh_partitionpoint, otherwise use
+ qh_findbestnew if merged new facet or sharpnewfacets.
+
+ See:
+ qh_DISToutside -- when is a point clearly outside of a facet
+ qh_SEARCHdist -- when is facet coplanar with the best facet?
+ qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="WIDEcoplanar">-</a>
+
+ qh_WIDEcoplanar
+ n*MAXcoplanar or n*MINvisible for a WIDEfacet
+
+ if vertex is further than qh.WIDEfacet from the hyperplane
+ then its ridges are not counted in computing the area, and
+ the facet's centrum is frozen.
+
+ notes:
+ qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+ qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="MAXnarrow">-</a>
+
+ qh_MAXnarrow
+ max. cosine in initial hull that sets qh.NARROWhull
+
+ notes:
+ If qh.NARROWhull, the initial partition does not make
+ coplanar points. If narrow, a coplanar point can be
+ coplanar to two facets of opposite orientations and
+ distant from the exact convex hull.
+
+ Conservative estimate. Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="WARNnarrow">-</a>
+
+ qh_WARNnarrow
+ max. cosine in initial hull to warn about qh.NARROWhull
+
+ notes:
+ this is a conservative estimate.
+ Don't actually see problems until it is -1.0. See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*-<a href="qh-user.htm#TOC"
+ >--------------------------------</a><a name="ZEROdelaunay">-</a>
+
+ qh_ZEROdelaunay
+ a zero Delaunay facet occurs for input sites coplanar with their convex hull
+ the last normal coefficient of a zero Delaunay facet is within
+ qh_ZEROdelaunay * qh.ANGLEround of 0
+
+ notes:
+ qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+ You can avoid zero Delaunay facets by surrounding the input with a box.
+
+ Use option 'PDk:-n' to explicitly define zero Delaunay facets
+ k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+ n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+#endif /* qh_DEFuser */
+
+
+
diff --git a/extern/qhull/src/user_eg.c b/extern/qhull/src/user_eg.c
new file mode 100644
index 00000000000..97e4aa7a89a
--- /dev/null
+++ b/extern/qhull/src/user_eg.c
@@ -0,0 +1,310 @@
+/*<html><pre> -<a href="qh-user.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ user_eg.c
+ sample code for calling qhull() from an application
+
+ call with:
+
+ user_eg "cube/diamond options" "delaunay options" "halfspace options"
+
+ for example:
+
+ user_eg # return summaries
+
+ user_eg "n" "o" "Fp" # return normals, OFF, points
+
+ user_eg "n Qt" "o" "Fp" # triangulated cube
+
+ user_eg "QR0 p" "QR0 v p" "QR0 Fp" # rotate input and return points
+ # 'v' returns Voronoi
+ # transform is rotated for halfspaces
+
+ main() makes three runs of qhull.
+
+ 1) compute the convex hull of a cube
+
+ 2a) compute the Delaunay triangulation of random points
+
+ 2b) find the Delaunay triangle closest to a point.
+
+ 3) compute the halfspace intersection of a diamond
+
+ notes:
+
+ For another example, see main() in unix.c and user_eg2.c.
+ These examples, call qh_qhull() directly. They allow
+ tighter control on the code loaded with Qhull.
+
+ For a simple C++ example, see qhull_interface.cpp
+
+ Summaries are sent to stderr if other output formats are used
+
+ compiled by 'make user_eg'
+
+ see qhull.h for data structures, macros, and user-callable functions.
+*/
+
+#include "qhull_a.h"
+
+/*-------------------------------------------------
+-internal function prototypes
+*/
+void print_summary (void);
+void makecube (coordT *points, int numpoints, int dim);
+void makeDelaunay (coordT *points, int numpoints, int dim, int seed);
+void findDelaunay (int dim);
+void makehalf (coordT *points, int numpoints, int dim);
+
+/*-------------------------------------------------
+-print_summary()
+*/
+void print_summary (void) {
+ facetT *facet;
+ int k;
+
+ printf ("\n%d vertices and %d facets with normals:\n",
+ qh num_vertices, qh num_facets);
+ FORALLfacets {
+ for (k=0; k < qh hull_dim; k++)
+ printf ("%6.2g ", facet->normal[k]);
+ printf ("\n");
+ }
+}
+
+/*--------------------------------------------------
+-makecube- set points to vertices of cube
+ points is numpoints X dim
+*/
+void makecube (coordT *points, int numpoints, int dim) {
+ int j,k;
+ coordT *point;
+
+ for (j=0; j<numpoints; j++) {
+ point= points + j*dim;
+ for (k=dim; k--; ) {
+ if (j & ( 1 << k))
+ point[k]= 1.0;
+ else
+ point[k]= -1.0;
+ }
+ }
+} /*.makecube.*/
+
+/*--------------------------------------------------
+-makeDelaunay- set points for dim Delaunay triangulation of random points
+ points is numpoints X dim.
+notes:
+ makeDelaunay() in user_eg2.c uses qh_setdelaunay() to project points in place.
+*/
+void makeDelaunay (coordT *points, int numpoints, int dim, int seed) {
+ int j,k;
+ coordT *point, realr;
+
+
+ printf ("seed: %d\n", seed);
+ qh_RANDOMseed_( seed);
+ for (j=0; j<numpoints; j++) {
+ point= points + j*dim;
+ for (k= 0; k < dim; k++) {
+ realr= qh_RANDOMint;
+ point[k]= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+ }
+ }
+} /*.makeDelaunay.*/
+
+/*--------------------------------------------------
+-findDelaunay- find Delaunay triangle for [0.5,0.5,...]
+ assumes dim < 100
+notes:
+ calls qh_setdelaunay() to project the point to a parabaloid
+*/
+void findDelaunay (int dim) {
+ int k;
+ coordT point[ 100];
+ boolT isoutside;
+ realT bestdist;
+ facetT *facet;
+ vertexT *vertex, **vertexp;
+
+ for (k= 0; k < dim; k++)
+ point[k]= 0.5;
+ qh_setdelaunay (dim+1, 1, point);
+ facet= qh_findbestfacet (point, qh_ALL, &bestdist, &isoutside);
+ FOREACHvertex_(facet->vertices) {
+ for (k=0; k < dim; k++)
+ printf ("%5.2f ", vertex->point[k]);
+ printf ("\n");
+ }
+} /*.findDelaunay.*/
+
+/*--------------------------------------------------
+-makehalf- set points to halfspaces for a (dim)-dimensional diamond
+ points is numpoints X dim+1
+
+ each halfspace consists of dim coefficients followed by an offset
+*/
+void makehalf (coordT *points, int numpoints, int dim) {
+ int j,k;
+ coordT *point;
+
+ for (j=0; j<numpoints; j++) {
+ point= points + j*(dim+1);
+ point[dim]= -1.0; /* offset */
+ for (k=dim; k--; ) {
+ if (j & ( 1 << k))
+ point[k]= 1.0;
+ else
+ point[k]= -1.0;
+ }
+ }
+} /*.makehalf.*/
+
+#define DIM 3 /* dimension of points, must be < 31 for SIZEcube */
+#define SIZEcube (1<<DIM)
+#define SIZEdiamond (2*DIM)
+#define TOTpoints (SIZEcube + SIZEdiamond)
+
+/*--------------------------------------------------
+-main- derived from call_qhull in user.c
+
+ see program header
+
+ this contains three runs of Qhull for convex hull, Delaunay
+ triangulation or Voronoi vertices, and halfspace intersection
+
+*/
+int main (int argc, char *argv[]) {
+ int dim= DIM; /* dimension of points */
+ int numpoints; /* number of points */
+ coordT points[(DIM+1)*TOTpoints]; /* array of coordinates for each point */
+ coordT *rows[TOTpoints];
+ boolT ismalloc= False; /* True if qhull should free points in qh_freeqhull() or reallocation */
+ char flags[250]; /* option flags for qhull, see qh_opt.htm */
+ FILE *outfile= stdout; /* output from qh_produce_output()
+ use NULL to skip qh_produce_output() */
+ FILE *errfile= stderr; /* error messages from qhull code */
+ int exitcode; /* 0 if no error from qhull */
+ facetT *facet; /* set by FORALLfacets */
+ int curlong, totlong; /* memory remaining after qh_memfreeshort */
+ int i;
+
+ printf ("This is the output from user_eg.c\n\n\
+It shows how qhull() may be called from an application. It is not part\n\
+of qhull itself. If it appears accidently, please remove user_eg.c from\n\
+your project.\n\n");
+
+ /*
+ Run 1: convex hull
+ */
+ printf( "\ncompute convex hull of cube after rotating input\n");
+ sprintf (flags, "qhull s Tcv %s", argc >= 2 ? argv[1] : "");
+ numpoints= SIZEcube;
+ makecube (points, numpoints, DIM);
+ for (i=numpoints; i--; )
+ rows[i]= points+dim*i;
+ qh_printmatrix (outfile, "input", rows, numpoints, dim);
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode) { /* if no error */
+ /* 'qh facet_list' contains the convex hull */
+ print_summary();
+ FORALLfacets {
+ /* ... your code ... */
+ }
+ }
+ qh_freeqhull(!qh_ALL); /* free long memory */
+ qh_memfreeshort (&curlong, &totlong); /* free short memory and memory allocator */
+ if (curlong || totlong)
+ fprintf (errfile, "qhull internal warning (user_eg, #1): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+
+ /*
+ Run 2: Delaunay triangulation
+ */
+
+ printf( "\ncompute 3-d Delaunay triangulation\n");
+ sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+ numpoints= SIZEcube;
+ makeDelaunay (points, numpoints, dim, time(NULL));
+ for (i=numpoints; i--; )
+ rows[i]= points+dim*i;
+ qh_printmatrix (outfile, "input", rows, numpoints, dim);
+ exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode) { /* if no error */
+ /* 'qh facet_list' contains the convex hull */
+ /* If you want a Voronoi diagram ('v') and do not request output (i.e., outfile=NULL),
+ call qh_setvoronoi_all() after qh_new_qhull(). */
+ print_summary();
+ FORALLfacets {
+ /* ... your code ... */
+ }
+ printf( "\nfind 3-d Delaunay triangle closest to [0.5, 0.5, ...]\n");
+ exitcode= setjmp (qh errexit);
+ if (!exitcode) {
+ /* Trap Qhull errors in findDelaunay(). Without the setjmp(), Qhull
+ will exit() after reporting an error */
+ qh NOerrexit= False;
+ findDelaunay (DIM);
+ }
+ qh NOerrexit= True;
+ }
+#if qh_QHpointer /* see user.h */
+ {
+ qhT *oldqhA, *oldqhB;
+ coordT pointsB[DIM*TOTpoints]; /* array of coordinates for each point */
+
+
+ printf( "\nsave first triangulation and compute a new triangulation\n");
+ oldqhA= qh_save_qhull();
+ sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+ numpoints= SIZEcube;
+ makeDelaunay (pointsB, numpoints, dim, time(NULL)+1);
+ for (i=numpoints; i--; )
+ rows[i]= pointsB+dim*i;
+ qh_printmatrix (outfile, "input", rows, numpoints, dim);
+ exitcode= qh_new_qhull (dim, numpoints, pointsB, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode)
+ print_summary();
+ printf( "\nsave second triangulation and restore first one\n");
+ oldqhB= qh_save_qhull();
+ qh_restore_qhull (&oldqhA);
+ print_summary();
+ printf( "\nfree first triangulation and restore second one.\n");
+ qh_freeqhull (qh_ALL); /* free short and long memory used by first call */
+ /* do not use qh_memfreeshort */
+ qh_restore_qhull (&oldqhB);
+ print_summary();
+ }
+#endif
+ qh_freeqhull(!qh_ALL); /* free long memory */
+ qh_memfreeshort (&curlong, &totlong); /* free short memory and memory allocator */
+ if (curlong || totlong)
+ fprintf (errfile, "qhull internal warning (user_eg, #2): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+
+ /*
+ Run 3: halfspace intersection about the origin
+ */
+ printf( "\ncompute halfspace intersection about the origin for a diamond\n");
+ sprintf (flags, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "Fp");
+ numpoints= SIZEcube;
+ makehalf (points, numpoints, dim);
+ for (i=numpoints; i--; )
+ rows[i]= points+(dim+1)*i;
+ qh_printmatrix (outfile, "input as halfspace coefficients + offsets", rows, numpoints, dim+1);
+ /* use qh_sethalfspace_all to transform the halfspaces yourself.
+ If so, set 'qh feasible_point and do not use option 'Hn,...' [it would retransform the halfspaces]
+ */
+ exitcode= qh_new_qhull (dim+1, numpoints, points, ismalloc,
+ flags, outfile, errfile);
+ if (!exitcode)
+ print_summary();
+ qh_freeqhull (!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong) /* could also check previous runs */
+ fprintf (stderr, "qhull internal warning (user_eg, #3): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+ return exitcode;
+} /* main */
+
diff --git a/extern/qhull/src/user_eg2.c b/extern/qhull/src/user_eg2.c
new file mode 100644
index 00000000000..1eb42ccfe8a
--- /dev/null
+++ b/extern/qhull/src/user_eg2.c
@@ -0,0 +1,532 @@
+/*<html><pre> -<a href="qh-qhull.htm"
+ >-------------------------------</a><a name="TOP">-</a>
+
+ user_eg2.c
+
+ sample code for calling qhull() from an application.
+
+ See user_eg.c for a simpler method using qh_new_qhull().
+ The method used here and in unix.c gives you additional
+ control over Qhull.
+
+ call with:
+
+ user_eg2 "triangulated cube/diamond options" "delaunay options" "halfspace options"
+
+ for example:
+
+ user_eg2 # return summaries
+
+ user_eg2 "n" "o" "Fp" # return normals, OFF, points
+
+ user_eg2 "QR0 p" "QR0 v p" "QR0 Fp" # rotate input and return points
+ # 'v' returns Voronoi
+ # transform is rotated for halfspaces
+
+ main() makes three runs of qhull.
+
+ 1) compute the convex hull of a cube, and incrementally add a diamond
+
+ 2a) compute the Delaunay triangulation of random points, and add points.
+
+ 2b) find the Delaunay triangle closest to a point.
+
+ 3) compute the halfspace intersection of a diamond, and add a cube
+
+ notes:
+
+ summaries are sent to stderr if other output formats are used
+
+ derived from unix.c and compiled by 'make user_eg2'
+
+ see qhull.h for data structures, macros, and user-callable functions.
+
+ If you want to control all output to stdio and input to stdin,
+ set the #if below to "1" and delete all lines that contain "io.c".
+ This prevents the loading of io.o. Qhull will
+ still write to 'qh ferr' (stderr) for error reporting and tracing.
+
+ Defining #if 1, also prevents user.o from being loaded.
+*/
+
+#include "qhull_a.h"
+
+/*-------------------------------------------------
+-internal function prototypes
+*/
+void print_summary (void);
+void makecube (coordT *points, int numpoints, int dim);
+void adddiamond (coordT *points, int numpoints, int numnew, int dim);
+void makeDelaunay (coordT *points, int numpoints, int dim);
+void addDelaunay (coordT *points, int numpoints, int numnew, int dim);
+void findDelaunay (int dim);
+void makehalf (coordT *points, int numpoints, int dim);
+void addhalf (coordT *points, int numpoints, int numnew, int dim, coordT *feasible);
+
+/*-------------------------------------------------
+-print_summary()
+*/
+void print_summary (void) {
+ facetT *facet;
+ int k;
+
+ printf ("\n%d vertices and %d facets with normals:\n",
+ qh num_vertices, qh num_facets);
+ FORALLfacets {
+ for (k=0; k < qh hull_dim; k++)
+ printf ("%6.2g ", facet->normal[k]);
+ printf ("\n");
+ }
+}
+
+/*--------------------------------------------------
+-makecube- set points to vertices of cube
+ points is numpoints X dim
+*/
+void makecube (coordT *points, int numpoints, int dim) {
+ int j,k;
+ coordT *point;
+
+ for (j=0; j<numpoints; j++) {
+ point= points + j*dim;
+ for (k=dim; k--; ) {
+ if (j & ( 1 << k))
+ point[k]= 1.0;
+ else
+ point[k]= -1.0;
+ }
+ }
+} /*.makecube.*/
+
+/*--------------------------------------------------
+-adddiamond- add diamond to convex hull
+ points is numpoints+numnew X dim.
+
+notes:
+ qh_addpoint() does not make a copy of the point coordinates.
+
+ For inside points and some outside points, qh_findbestfacet performs
+ an exhaustive search for a visible facet. Algorithms that retain
+ previously constructed hulls should be faster for on-line construction
+ of the convex hull.
+*/
+void adddiamond (coordT *points, int numpoints, int numnew, int dim) {
+ int j,k;
+ coordT *point;
+ facetT *facet;
+ boolT isoutside;
+ realT bestdist;
+
+ for (j= 0; j < numnew ; j++) {
+ point= points + (numpoints+j)*dim;
+ if (points == qh first_point) /* in case of 'QRn' */
+ qh num_points= numpoints+j+1;
+ /* qh num_points sets the size of the points array. You may
+ allocate the points elsewhere. If so, qh_addpoint records
+ the point's address in qh other_points
+ */
+ for (k=dim; k--; ) {
+ if (j/2 == k)
+ point[k]= (j & 1) ? 2.0 : -2.0;
+ else
+ point[k]= 0.0;
+ }
+ facet= qh_findbestfacet (point, !qh_ALL, &bestdist, &isoutside);
+ if (isoutside) {
+ if (!qh_addpoint (point, facet, False))
+ break; /* user requested an early exit with 'TVn' or 'TCn' */
+ }
+ printf ("%d vertices and %d facets\n",
+ qh num_vertices, qh num_facets);
+ /* qh_produce_output(); */
+ }
+ if (qh DOcheckmax)
+ qh_check_maxout();
+ else if (qh KEEPnearinside)
+ qh_nearcoplanar();
+} /*.adddiamond.*/
+
+/*--------------------------------------------------
+-makeDelaunay- set points for dim-1 Delaunay triangulation of random points
+ points is numpoints X dim. Each point is projected to a paraboloid.
+*/
+void makeDelaunay (coordT *points, int numpoints, int dim) {
+ int j,k, seed;
+ coordT *point, realr;
+
+ seed= time(NULL);
+ printf ("seed: %d\n", seed);
+ qh_RANDOMseed_( seed);
+ for (j=0; j<numpoints; j++) {
+ point= points + j*dim;
+ for (k= 0; k < dim-1; k++) {
+ realr= qh_RANDOMint;
+ point[k]= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+ }
+ }
+ qh_setdelaunay (dim, numpoints, points);
+} /*.makeDelaunay.*/
+
+/*--------------------------------------------------
+-addDelaunay- add points to dim-1 Delaunay triangulation
+ points is numpoints+numnew X dim. Each point is projected to a paraboloid.
+notes:
+ qh_addpoint() does not make a copy of the point coordinates.
+
+ Since qh_addpoint() is not given a visible facet, it performs a directed
+ search of all facets. Algorithms that retain previously
+ constructed hulls may be faster.
+*/
+void addDelaunay (coordT *points, int numpoints, int numnew, int dim) {
+ int j,k;
+ coordT *point, realr;
+ facetT *facet;
+ realT bestdist;
+ boolT isoutside;
+
+ for (j= 0; j < numnew ; j++) {
+ point= points + (numpoints+j)*dim;
+ if (points == qh first_point) /* in case of 'QRn' */
+ qh num_points= numpoints+j+1;
+ /* qh num_points sets the size of the points array. You may
+ allocate the point elsewhere. If so, qh_addpoint records
+ the point's address in qh other_points
+ */
+ for (k= 0; k < dim-1; k++) {
+ realr= qh_RANDOMint;
+ point[k]= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+ }
+ qh_setdelaunay (dim, 1, point);
+ facet= qh_findbestfacet (point, !qh_ALL, &bestdist, &isoutside);
+ if (isoutside) {
+ if (!qh_addpoint (point, facet, False))
+ break; /* user requested an early exit with 'TVn' or 'TCn' */
+ }
+ qh_printpoint (stdout, "added point", point);
+ printf ("%d points, %d extra points, %d vertices, and %d facets in total\n",
+ qh num_points, qh_setsize (qh other_points),
+ qh num_vertices, qh num_facets);
+
+ /* qh_produce_output(); */
+ }
+ if (qh DOcheckmax)
+ qh_check_maxout();
+ else if (qh KEEPnearinside)
+ qh_nearcoplanar();
+} /*.addDelaunay.*/
+
+/*--------------------------------------------------
+-findDelaunay- find Delaunay triangle for [0.5,0.5,...]
+ assumes dim < 100
+*/
+void findDelaunay (int dim) {
+ int k;
+ coordT point[ 100];
+ boolT isoutside;
+ realT bestdist;
+ facetT *facet;
+ vertexT *vertex, **vertexp;
+
+ for (k= 0; k < dim-1; k++)
+ point[k]= 0.5;
+ qh_setdelaunay (dim, 1, point);
+ facet= qh_findbestfacet (point, qh_ALL, &bestdist, &isoutside);
+ FOREACHvertex_(facet->vertices) {
+ for (k=0; k < dim-1; k++)
+ printf ("%5.2f ", vertex->point[k]);
+ printf ("\n");
+ }
+} /*.findDelaunay.*/
+
+/*--------------------------------------------------
+-makehalf- set points to halfspaces for a (dim)-d diamond
+ points is numpoints X dim+1
+
+ each halfspace consists of dim coefficients followed by an offset
+*/
+void makehalf (coordT *points, int numpoints, int dim) {
+ int j,k;
+ coordT *point;
+
+ for (j=0; j<numpoints; j++) {
+ point= points + j*(dim+1);
+ point[dim]= -1.0; /* offset */
+ for (k=dim; k--; ) {
+ if (j & ( 1 << k))
+ point[k]= 1.0;
+ else
+ point[k]= -1.0;
+ }
+ }
+} /*.makehalf.*/
+
+/*--------------------------------------------------
+-addhalf- add halfspaces for a (dim)-d cube to the intersection
+ points is numpoints+numnew X dim+1
+notes:
+ assumes dim < 100.
+
+ For makehalf(), points is the initial set of halfspaces with offsets.
+ It is transformed by qh_sethalfspace_all into a
+ (dim)-d set of newpoints. Qhull computed the convex hull of newpoints -
+ this is equivalent to the halfspace intersection of the
+ orginal halfspaces.
+
+ For addhalf(), the remainder of points stores the transforms of
+ the added halfspaces. Qhull computes the convex hull of newpoints
+ and the added points. qh_addpoint() does not make a copy of these points.
+
+ Since halfspace intersection is equivalent to a convex hull,
+ qh_findbestfacet may perform an exhaustive search
+ for a visible facet. Algorithms that retain previously constructed
+ intersections should be faster for on-line construction.
+*/
+void addhalf (coordT *points, int numpoints, int numnew, int dim, coordT *feasible) {
+ int j,k;
+ coordT *point, normal[100], offset, *next;
+ facetT *facet;
+ boolT isoutside;
+ realT bestdist;
+
+ for (j= 0; j < numnew ; j++) {
+ offset= -1.0;
+ for (k=dim; k--; ) {
+ if (j/2 == k) {
+ normal[k]= sqrt (dim); /* to normalize as in makehalf */
+ if (j & 1)
+ normal[k]= -normal[k];
+ }else
+ normal[k]= 0.0;
+ }
+ point= points + (numpoints+j)* (dim+1); /* does not use point[dim] */
+ qh_sethalfspace (dim, point, &next, normal, &offset, feasible);
+ facet= qh_findbestfacet (point, !qh_ALL, &bestdist, &isoutside);
+ if (isoutside) {
+ if (!qh_addpoint (point, facet, False))
+ break; /* user requested an early exit with 'TVn' or 'TCn' */
+ }
+ qh_printpoint (stdout, "added offset -1 and normal", normal);
+ printf ("%d points, %d extra points, %d vertices, and %d facets in total\n",
+ qh num_points, qh_setsize (qh other_points),
+ qh num_vertices, qh num_facets);
+ /* qh_produce_output(); */
+ }
+ if (qh DOcheckmax)
+ qh_check_maxout();
+ else if (qh KEEPnearinside)
+ qh_nearcoplanar();
+} /*.addhalf.*/
+
+#define DIM 3 /* dimension of points, must be < 31 for SIZEcube */
+#define SIZEcube (1<<DIM)
+#define SIZEdiamond (2*DIM)
+#define TOTpoints (SIZEcube + SIZEdiamond)
+
+/*--------------------------------------------------
+-main- derived from call_qhull in user.c
+
+ see program header
+
+ this contains three runs of Qhull for convex hull, Delaunay
+ triangulation or Voronoi vertices, and halfspace intersection
+
+*/
+int main (int argc, char *argv[]) {
+ boolT ismalloc;
+ int curlong, totlong, exitcode;
+ char options [2000];
+
+ printf ("This is the output from user_eg2.c\n\n\
+It shows how qhull() may be called from an application. It is not part\n\
+of qhull itself. If it appears accidently, please remove user_eg2.c from\n\
+your project.\n\n");
+ ismalloc= False; /* True if qh_freeqhull should 'free(array)' */
+ /*
+ Run 1: convex hull
+ */
+ qh_init_A (stdin, stdout, stderr, 0, NULL);
+ exitcode= setjmp (qh errexit);
+ if (!exitcode) {
+ coordT array[TOTpoints][DIM];
+
+ strcat (qh rbox_command, "user_eg cube");
+ sprintf (options, "qhull s Tcv Q11 %s ", argc >= 2 ? argv[1] : "");
+ qh_initflags (options);
+ printf( "\ncompute triangulated convex hull of cube after rotating input\n");
+ makecube (array[0], SIZEcube, DIM);
+ qh_init_B (array[0], SIZEcube, DIM, ismalloc);
+ qh_qhull();
+ qh_check_output();
+ qh_triangulate(); /* requires option 'Q11' if want to add points */
+ print_summary ();
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ printf( "\nadd points in a diamond\n");
+ adddiamond (array[0], SIZEcube, SIZEdiamond, DIM);
+ qh_check_output();
+ print_summary ();
+ qh_produce_output(); /* delete this line to help avoid io.c */
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ }
+ qh NOerrexit= True;
+ qh_freeqhull (!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ /*
+ Run 2: Delaunay triangulation
+ */
+ qh_init_A (stdin, stdout, stderr, 0, NULL);
+ exitcode= setjmp (qh errexit);
+ if (!exitcode) {
+ coordT array[TOTpoints][DIM];
+
+ strcat (qh rbox_command, "user_eg Delaunay");
+ sprintf (options, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+ qh_initflags (options);
+ printf( "\ncompute 2-d Delaunay triangulation\n");
+ makeDelaunay (array[0], SIZEcube, DIM);
+ /* Instead of makeDelaunay with qh_setdelaunay, you may
+ produce a 2-d array of points, set DIM to 2, and set
+ qh PROJECTdelaunay to True. qh_init_B will call
+ qh_projectinput to project the points to the paraboloid
+ and add a point "at-infinity".
+ */
+ qh_init_B (array[0], SIZEcube, DIM, ismalloc);
+ qh_qhull();
+ /* If you want Voronoi ('v') without qh_produce_output(), call
+ qh_setvoronoi_all() after qh_qhull() */
+ qh_check_output();
+ print_summary ();
+ qh_produce_output(); /* delete this line to help avoid io.c */
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ printf( "\nadd points to triangulation\n");
+ addDelaunay (array[0], SIZEcube, SIZEdiamond, DIM);
+ qh_check_output();
+ qh_produce_output(); /* delete this line to help avoid io.c */
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ printf( "\nfind Delaunay triangle closest to [0.5, 0.5, ...]\n");
+ findDelaunay (DIM);
+ }
+ qh NOerrexit= True;
+ qh_freeqhull (!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ /*
+ Run 3: halfspace intersection
+ */
+ qh_init_A (stdin, stdout, stderr, 0, NULL);
+ exitcode= setjmp (qh errexit);
+ if (!exitcode) {
+ coordT array[TOTpoints][DIM+1]; /* +1 for halfspace offset */
+ pointT *points;
+
+ strcat (qh rbox_command, "user_eg halfspaces");
+ sprintf (options, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "");
+ qh_initflags (options);
+ printf( "\ncompute halfspace intersection about the origin for a diamond\n");
+ makehalf (array[0], SIZEcube, DIM);
+ qh_setfeasible (DIM); /* from io.c, sets qh feasible_point from 'Hn,n' */
+ /* you may malloc and set qh feasible_point directly. It is only used for
+ option 'Fp' */
+ points= qh_sethalfspace_all ( DIM+1, SIZEcube, array[0], qh feasible_point);
+ qh_init_B (points, SIZEcube, DIM, True); /* qh_freeqhull frees points */
+ qh_qhull();
+ qh_check_output();
+ qh_produce_output(); /* delete this line to help avoid io.c */
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ printf( "\nadd halfspaces for cube to intersection\n");
+ addhalf (array[0], SIZEcube, SIZEdiamond, DIM, qh feasible_point);
+ qh_check_output();
+ qh_produce_output(); /* delete this line to help avoid io.c */
+ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+ qh_check_points ();
+ }
+ qh NOerrexit= True;
+ qh NOerrexit= True;
+ qh_freeqhull (!qh_ALL);
+ qh_memfreeshort (&curlong, &totlong);
+ if (curlong || totlong) /* could also check previous runs */
+ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+ totlong, curlong);
+ return exitcode;
+} /* main */
+
+#if 1 /* use 1 to prevent loading of io.o and user.o */
+/*-------------------------------------------
+-errexit- return exitcode to system after an error
+ assumes exitcode non-zero
+ prints useful information
+ see qh_errexit2() in qhull.c for 2 facets
+*/
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
+
+ if (qh ERREXITcalled) {
+ fprintf (qh ferr, "qhull error while processing previous error. Exit program\n");
+ exit(1);
+ }
+ qh ERREXITcalled= True;
+ if (!qh QHULLfinished)
+ qh hulltime= (unsigned)clock() - qh hulltime;
+ fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
+ fprintf(qh ferr, "Options selected:\n%s\n", qh qhull_options);
+ if (qh furthest_id >= 0) {
+ fprintf(qh ferr, "\nLast point added to hull was p%d", qh furthest_id);
+ if (zzval_(Ztotmerge))
+ fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge));
+ if (qh QHULLfinished)
+ fprintf(qh ferr, "\nQhull has finished constructing the hull.");
+ else if (qh POSTmerging)
+ fprintf(qh ferr, "\nQhull has started post-merging");
+ fprintf(qh ferr, "\n\n");
+ }
+ if (qh NOerrexit) {
+ fprintf (qh ferr, "qhull error while ending program. Exit program\n");
+ exit(1);
+ }
+ if (!exitcode)
+ exitcode= qh_ERRqhull;
+ qh NOerrexit= True;
+ longjmp(qh errexit, exitcode);
+} /* errexit */
+
+
+/*-------------------------------------------
+-errprint- prints out the information of the erroneous object
+ any parameter may be NULL, also prints neighbors and geomview output
+*/
+void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+
+ fprintf (qh ferr, "%s facets f%d f%d ridge r%d vertex v%d\n",
+ string, getid_(atfacet), getid_(otherfacet), getid_(atridge),
+ getid_(atvertex));
+} /* errprint */
+
+
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
+ facetT *facet, **facetp;
+
+ /* remove these calls to help avoid io.c */
+ qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);/*io.c*/
+ FORALLfacet_(facetlist) /*io.c*/
+ qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall); /*io.c*/
+ FOREACHfacet_(facets) /*io.c*/
+ qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall); /*io.c*/
+ qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall); /*io.c*/
+
+ FORALLfacet_(facetlist)
+ fprintf( qh ferr, "facet f%d\n", facet->id);
+} /* printfacetlist */
+
+
+
+/*-----------------------------------------
+-user_memsizes- allocate up to 10 additional, quick allocation sizes
+*/
+void qh_user_memsizes (void) {
+
+ /* qh_memsize (size); */
+} /* user_memsizes */
+
+#endif
diff --git a/extern/solid/CMakeLists.txt b/extern/solid/CMakeLists.txt
new file mode 100644
index 00000000000..7840dd6b423
--- /dev/null
+++ b/extern/solid/CMakeLists.txt
@@ -0,0 +1,34 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+SET(INC include src src/broad src/complex src/convex ../qhull/include)
+
+FILE(GLOB SRC src/*.cpp src/convex/*.cpp src/complex/*.cpp src/broad/*.cpp)
+
+ADD_DEFINITIONS(-DUSE_DOUBLES -DQHULL -D_LIB)
+
+BLENDERLIB(extern_solid "${SRC}" "${INC}")
+#, libtype=['game2','player'], priority=[45, 75]
diff --git a/extern/solid/LICENSE_GPL.txt b/extern/solid/LICENSE_GPL.txt
new file mode 100644
index 00000000000..07db89585a2
--- /dev/null
+++ b/extern/solid/LICENSE_GPL.txt
@@ -0,0 +1,349 @@
+
+ The SOLID library is Copyright (C) 2001-2003 Dtecta.
+
+ You may use, distribute and copy the SOLID library under the terms of
+ GNU General Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
diff --git a/extern/solid/LICENSE_QPL.txt b/extern/solid/LICENSE_QPL.txt
new file mode 100644
index 00000000000..3fca00466e2
--- /dev/null
+++ b/extern/solid/LICENSE_QPL.txt
@@ -0,0 +1,110 @@
+
+ The SOLID library is Copyright (C) 2001-2003 Dtecta.
+
+ You may use, distribute and copy the SOLID library under the terms of
+ the Q Public License, which is displayed below.
+
+-------------------------------------------------------------------------
+ THE Q PUBLIC LICENSE
+ version 1.0
+
+ Copyright (C) 1999-2000 Trolltech AS, Norway.
+ Everyone is permitted to copy and
+ distribute this license document.
+
+The intent of this license is to establish freedom to share and change the
+software regulated by this license under the open source model.
+
+This license applies to any software containing a notice placed by the
+copyright holder saying that it may be distributed under the terms of
+the Q Public License version 1.0. Such software is herein referred to as
+the Software. This license covers modification and distribution of the
+Software, use of third-party application programs based on the Software,
+and development of free software which uses the Software.
+
+ Granted Rights
+
+1. You are granted the non-exclusive rights set forth in this license
+ provided you agree to and comply with any and all conditions in this
+ license. Whole or partial distribution of the Software, or software
+ items that link with the Software, in any form signifies acceptance of
+ this license.
+
+2. You may copy and distribute the Software in unmodified form provided
+ that the entire package, including - but not restricted to - copyright,
+ trademark notices and disclaimers, as released by the initial developer
+ of the Software, is distributed.
+
+3. You may make modifications to the Software and distribute your
+ modifications, in a form that is separate from the Software, such as
+ patches. The following restrictions apply to modifications:
+
+ a. Modifications must not alter or remove any copyright notices in
+ the Software.
+
+ b. When modifications to the Software are released under this
+ license, a non-exclusive royalty-free right is granted to the
+ initial developer of the Software to distribute your modification
+ in future versions of the Software provided such versions remain
+ available under these terms in addition to any other license(s) of
+ the initial developer.
+
+4. You may distribute machine-executable forms of the Software or
+ machine-executable forms of modified versions of the Software, provided
+ that you meet these restrictions:
+
+ a. You must include this license document in the distribution.
+
+ b. You must ensure that all recipients of the machine-executable forms
+ are also able to receive the complete machine-readable source code
+ to the distributed Software, including all modifications, without
+ any charge beyond the costs of data transfer, and place prominent
+ notices in the distribution explaining this.
+
+ c. You must ensure that all modifications included in the
+ machine-executable forms are available under the terms of this
+ license.
+
+5. You may use the original or modified versions of the Software to
+ compile, link and run application programs legally developed by you
+ or by others.
+
+6. You may develop application programs, reusable components and other
+ software items that link with the original or modified versions of the
+ Software. These items, when distributed, are subject to the following
+ requirements:
+
+ a. You must ensure that all recipients of machine-executable forms of
+ these items are also able to receive and use the complete
+ machine-readable source code to the items without any charge
+ beyond the costs of data transfer.
+
+ b. You must explicitly license all recipients of your items to use
+ and re-distribute original and modified versions of the items in
+ both machine-executable and source code forms. The recipients must
+ be able to do so without any charges whatsoever, and they must be
+ able to re-distribute to anyone they choose.
+
+
+ c. If the items are not available to the general public, and the
+ initial developer of the Software requests a copy of the items,
+ then you must supply one.
+
+ Limitations of Liability
+
+In no event shall the initial developers or copyright holders be liable
+for any damages whatsoever, including - but not restricted to - lost
+revenue or profits or other direct, indirect, special, incidental or
+consequential damages, even if they have been advised of the possibility
+of such damages, except to the extent invariable law, if any, provides
+otherwise.
+
+ No Warranty
+
+The Software and this license document are provided AS IS with NO WARRANTY
+OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE.
+ Choice of Law
+
+This license is governed by the Laws of Norway. Disputes shall be settled
+by Oslo City Court.
diff --git a/extern/solid/Makefile b/extern/solid/Makefile
new file mode 100644
index 00000000000..206dc21c3fb
--- /dev/null
+++ b/extern/solid/Makefile
@@ -0,0 +1,56 @@
+# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# vim: tabstop=8
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): GSR
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+include nan_definitions.mk
+
+SOURCEDIR = extern/solid
+LIBNAMES = solid solid_broad solid_convex solid_complex
+DIR = $(OCGDIR)/extern/
+DIRS = src
+
+include nan_subdirs.mk
+
+install: $(ALL_OR_DEBUG)
+ @[ -d $(NAN_SOLID) ] || mkdir -p $(NAN_SOLID)
+ @[ -d $(NAN_SOLID)/include/SOLID ] || mkdir -p $(NAN_SOLID)/include/SOLID
+ @[ -d $(NAN_SOLID)/include/SOLID/MT ] || mkdir -p $(NAN_SOLID)/include/SOLID/MT
+ @[ -d $(NAN_SOLID)/lib/$(DEBUG_DIR) ] || mkdir -p $(NAN_SOLID)/lib/$(DEBUG_DIR)
+ @for i in $(LIBNAMES); do \
+ $(NANBLENDERHOME)/intern/tools/cpifdiff.sh $(DIR)/$$i/$(DEBUG_DIR)lib$$i.a $(NAN_SOLID)/lib/$(DEBUG_DIR) ; \
+ if [ $(OS) = darwin ] ; then \
+ ranlib $(NAN_SOLID)/lib/$(DEBUG_DIR)lib$$i.a ; \
+ fi ; \
+ done
+ @$(NANBLENDERHOME)/intern/tools/cpifdiff.sh include/*.h $(NAN_SOLID)/include/SOLID
+ @$(NANBLENDERHOME)/intern/tools/cpifdiff.sh include/MT/*.h $(NAN_SOLID)/include/SOLID/MT
+
+
diff --git a/extern/solid/README.txt b/extern/solid/README.txt
new file mode 100644
index 00000000000..348d92b35cb
--- /dev/null
+++ b/extern/solid/README.txt
@@ -0,0 +1,55 @@
+
+ SOLID - Software Library for Interference Detection
+
+SOLID is a software library containing functions for performing
+intersection tests and proximity queries that are useful in the context
+of collision detection. Collision detection is the process of detecting
+pairs of geometric objects that are intersecting or are within a given
+proximity of each other. In particular, SOLID is useful for detecting
+collisions between objects that are moving relatively of each other over
+time. The motions of objects are controlled by the client application,
+and are not determined or affected by SOLID.
+
+This open-source edition of SOLID version 3 is released under the terms of
+either the GNU Public License (GPL) or the Q Public License (QPL). This means
+that for software created with SOLID version 3 you must comply with the terms
+of one of these licenses. You may choose wich of these licenses best suits
+your purpose. See the following files contained in this distribution for a
+complete list of terms and conditions of these licenses:
+
+ LICENSE_QPL.txt The Q Public License
+ LICENSE_GPL.txt The GNU General Public License
+
+These licenses do not permit the use of SOLID 3 in closed-source software
+products. For enquiries about commercial use of SOLID, please contact
+info@dtecta.com.
+
+SOLID 3 uses Qhull from The Geometry Center of the University of Minnesota.
+Qhull is copyrighted as noted below. Qhull is free software and may be
+obtained via anonymous ftp from geom.umn.edu.
+
+ Qhull, Copyright (c) 1993-2002
+
+ The National Science and Technology Research Center for
+ Computation and Visualization of Geometric Structures
+ (The Geometry Center)
+ University of Minnesota
+ 400 Lind Hall
+ 207 Church Street S.E.
+ Minneapolis, MN 55455 USA
+
+ email: qhull@geom.umn.edu
+
+Installation
+
+For details on how to install SOLID see the documention in the 'doc' directory.
+
+Platforms
+
+SOLID 3 has been tested on the following platforms:
+
+ Linux IA32 gcc 2.95.3, gcc 3.3
+ Win32 MSVC++ 6.0 SP4, MSVC++ 7.1
+
+
+
diff --git a/extern/solid/SConscript b/extern/solid/SConscript
new file mode 100644
index 00000000000..8c54442ca73
--- /dev/null
+++ b/extern/solid/SConscript
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+import sys
+
+Import('env')
+
+defs = 'USE_DOUBLES QHULL _LIB'
+cflags = []
+
+if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
+ defs += ' WIN32 NDEBUG _WINDOWS _LIB'
+ cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6']
+elif env['OURPLATFORM']=='win32-mingw':
+ defs += ' NDEBUG'
+ cflags += ['-O2']
+elif sys.platform=='linux2' or sys.platform=='linux-i386' or sys.platform=='freebsd4' or sys.platform=='freebsd5' or sys.platform=='openbsd3' or sys.platform=='sunos5':
+ defs += ' NDEBUG'
+ cflags += ['-O2']
+elif sys.platform=='darwin' :
+ defs += ' NDEBUG'
+ cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math']
+
+else:
+ print "################################################"
+ print
+ print "Check if solid builds on your platform correctly"
+ print "Add your platform specific defines"
+ print "and cflags / cxxflags to the"
+ print "extern/solid/SConscript file"
+
+sources = env.Glob('src/*.cpp') + env.Glob('src/convex/*.cpp') + env.Glob('src/complex/*.cpp') + env.Glob('src/broad/*.cpp')
+
+incs = 'include src src/broad src/complex src/convex ../qhull/include'
+
+env.BlenderLib ( libname='extern_solid', sources=sources, includes=Split(incs), defines=Split(defs), libtype=['extern'], priority=[10] , compileflags = cflags)
diff --git a/extern/solid/SOLID/SOLID.h b/extern/solid/SOLID/SOLID.h
new file mode 100644
index 00000000000..37d74340f8c
--- /dev/null
+++ b/extern/solid/SOLID/SOLID.h
@@ -0,0 +1,279 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_H
+#define SOLID_H
+
+#include "SOLID_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ DT_DECLARE_HANDLE(DT_ObjectHandle);
+ DT_DECLARE_HANDLE(DT_SceneHandle);
+ DT_DECLARE_HANDLE(DT_ShapeHandle);
+ DT_DECLARE_HANDLE(DT_VertexBaseHandle);
+ DT_DECLARE_HANDLE(DT_RespTableHandle);
+ DT_DECLARE_HANDLE(DT_ArchiveHandle);
+
+ typedef unsigned int DT_ResponseClass;
+
+ typedef enum DT_ResponseType {
+ DT_NO_RESPONSE, /* No response (obsolete) */
+ DT_BROAD_RESPONSE,
+ DT_SIMPLE_RESPONSE, /* No collision data */
+ DT_WITNESSED_RESPONSE, /* A point common to both objects
+ is returned as collision data
+ */
+ DT_DEPTH_RESPONSE /* The penetration depth is returned
+ as collision data. The penetration depth
+ is the shortest vector over which one
+ object needs to be translated in order
+ to bring the objects in touching contact.
+ */
+ } DT_ResponseType;
+
+/* For witnessed response, the following structure represents a common point. The world
+ coordinates of 'point1' and 'point2' coincide. 'normal' is the zero vector.
+
+ For depth response, the following structure represents the penetration depth.
+ 'point1' en 'point2' are the witness points of the penetration depth in world coordinates.
+ The penetration depth vector in world coordinates is represented by 'normal'.
+*/
+
+ typedef struct DT_CollData {
+ DT_Vector3 point1; /* Point in object1 in world coordinates */
+ DT_Vector3 point2; /* Point in object2 in world coordinates */
+ DT_Vector3 normal; /* point2 - point1 */
+ } DT_CollData;
+
+/* A response callback is called by SOLID for each pair of collding objects. 'client-data'
+ is a pointer to an arbitrary structure in the client application. The client objects are
+ pointers to structures in the client application associated with the coliding objects.
+ 'coll_data' is the collision data computed by SOLID.
+*/
+
+ typedef DT_Bool (*DT_ResponseCallback)(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+/* Shape definition */
+
+
+ extern DECLSPEC DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+ extern DECLSPEC DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height);
+ extern DECLSPEC DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height);
+ extern DECLSPEC DT_ShapeHandle DT_NewSphere(DT_Scalar radius);
+ extern DECLSPEC DT_ShapeHandle DT_NewPoint(const DT_Vector3 point);
+ extern DECLSPEC DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target);
+ extern DECLSPEC DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
+ extern DECLSPEC DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
+
+ extern DECLSPEC DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride);
+ extern DECLSPEC void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer);
+
+ extern DECLSPEC DT_ShapeHandle DT_NewComplexShape(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_EndComplexShape();
+
+ extern DECLSPEC DT_ShapeHandle DT_NewPolytope(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_EndPolytope();
+
+ extern DECLSPEC void DT_Begin();
+ extern DECLSPEC void DT_End();
+
+ extern DECLSPEC void DT_Vertex(const DT_Vector3 vertex);
+ extern DECLSPEC void DT_VertexIndex(DT_Index index);
+
+ extern DECLSPEC void DT_VertexIndices(DT_Count count, const DT_Index *indices);
+ extern DECLSPEC void DT_VertexRange(DT_Index first, DT_Count count);
+
+ extern DECLSPEC void DT_DeleteShape(DT_ShapeHandle shape);
+
+/* Object */
+
+ extern DECLSPEC DT_ObjectHandle DT_CreateObject(
+ void *client_object, /* pointer to object in client memory */
+ DT_ShapeHandle shape /* the shape or geometry of the object */
+ );
+
+ extern DECLSPEC void DT_DestroyObject(DT_ObjectHandle object);
+
+
+
+ extern DECLSPEC void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
+ extern DECLSPEC void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
+ extern DECLSPEC void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
+
+/* The margin is an offset from the actual shape. The actual geometry of an
+ object is the set of points whose distance to the transformed shape is at
+ most the margin. During the lifetime of an object the margin can be
+ modified.
+*/
+
+ extern DECLSPEC void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
+
+
+/* These commands assume a column-major 4x4 OpenGL matrix representation */
+
+ extern DECLSPEC void DT_SetMatrixf(DT_ObjectHandle object, const float *m);
+ extern DECLSPEC void DT_GetMatrixf(DT_ObjectHandle object, float *m);
+
+ extern DECLSPEC void DT_SetMatrixd(DT_ObjectHandle object, const double *m);
+ extern DECLSPEC void DT_GetMatrixd(DT_ObjectHandle object, double *m);
+
+ extern DECLSPEC void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max);
+
+
+ extern DECLSPEC DT_Bool DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 v);
+/* This next command returns the distance between the objects. De returned
+ closest points are given in world coordinates.
+*/
+ extern DECLSPEC DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+ extern DECLSPEC DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point);
+
+ extern DECLSPEC DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+/* Scene */
+
+ extern DECLSPEC DT_SceneHandle DT_CreateScene();
+ extern DECLSPEC void DT_DestroyScene(DT_SceneHandle scene);
+
+ extern DECLSPEC void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
+ extern DECLSPEC void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
+
+/* Note that objects can be assigned to multiple scenes! */
+
+/* Response */
+
+/* Response tables are defined independent of the scenes in which they are used.
+ Multiple response tables can be used in one scene, and a response table
+ can be shared among scenes.
+*/
+ extern DECLSPEC DT_RespTableHandle DT_CreateRespTable();
+ extern DECLSPEC void DT_DestroyRespTable(DT_RespTableHandle respTable);
+
+/* Responses are defined on (pairs of) response classes. Each response table
+ maintains its set of response classes.
+*/
+ extern DECLSPEC DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable);
+
+/* To each object for which a response is defined in the response table a
+ response class needs to be assigned.
+*/
+
+ extern DECLSPEC void DT_SetResponseClass(DT_RespTableHandle respTable,
+ DT_ObjectHandle object,
+ DT_ResponseClass responseClass);
+
+ extern DECLSPEC void DT_ClearResponseClass(DT_RespTableHandle respTable,
+ DT_ObjectHandle object);
+
+ extern DECLSPEC void DT_CallResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ const DT_CollData *coll_data);
+
+/* For each pair of objects multiple responses can be defined. A response is a callback
+ together with its response type and client data. */
+
+/* Responses can be defined for all pairs of response classes... */
+ extern DECLSPEC void DT_AddDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+
+ extern DECLSPEC void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response);
+/* ...per response class... */
+ extern DECLSPEC void DT_AddClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+
+ extern DECLSPEC void DT_RemoveClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response);
+
+/* ... and per pair of response classes...*/
+ extern DECLSPEC void DT_AddPairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+ extern DECLSPEC void DT_RemovePairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response);
+
+/* The next command calls the response callbacks for all intersecting pairs of objects in a scene.
+ 'DT_Test' returns the number of pairs of objects for which callbacks have been called.
+*/
+
+ extern DECLSPEC DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
+
+/* Set the maximum relative error in the closest points and penetration depth
+ computation. The default for `max_error' is 1.0e-3. Larger errors result
+ in better performance. Non-positive error tolerances are ignored.
+*/
+
+ extern DECLSPEC void DT_SetAccuracy(DT_Scalar max_error);
+
+/* Set the maximum tolerance on relative errors due to rounding. The default for `tol_error'
+ is the machine epsilon. Very large tolerances result in false collisions. Setting tol_error too small
+ results in missed collisions. Non-positive error tolerances are ignored.
+*/
+
+ extern DECLSPEC void DT_SetTolerance(DT_Scalar tol_error);
+
+
+/* This function returns the client pointer to the first object in a scene hit by the ray
+ (actually a line segment) defined by the points 'from' en 'to'. The spot is the hit point
+ on the object in local coordinates. 'normal' is the normal to the surface of the object in
+ world coordinates. The ignore_client pointer is used to make one of the objects transparent.
+
+ NB: Currently ray tests are implemented for spheres, boxes, and meshes only!!
+*/
+
+ extern DECLSPEC void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
+
+/* Similar, only here a single object is tested and a boolean is returned */
+
+ extern DECLSPEC DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/solid/SOLID/SOLID_broad.h b/extern/solid/SOLID/SOLID_broad.h
new file mode 100644
index 00000000000..74e4214fa67
--- /dev/null
+++ b/extern/solid/SOLID/SOLID_broad.h
@@ -0,0 +1,75 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_BROAD_H
+#define SOLID_BROAD_H
+
+#include "SOLID_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ DT_DECLARE_HANDLE(BP_SceneHandle);
+ DT_DECLARE_HANDLE(BP_ProxyHandle);
+
+ typedef void (*BP_Callback)(void *client_data,
+ void *object1,
+ void *object2);
+
+ typedef bool (*BP_RayCastCallback)(void *client_data,
+ void *object,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda);
+
+ extern DECLSPEC BP_SceneHandle BP_CreateScene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap);
+
+ extern DECLSPEC void BP_DestroyScene(BP_SceneHandle scene);
+
+ extern DECLSPEC BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene,
+ void *object,
+ const DT_Vector3 min,
+ const DT_Vector3 max);
+
+ extern DECLSPEC void BP_DestroyProxy(BP_SceneHandle scene,
+ BP_ProxyHandle proxy);
+
+ extern DECLSPEC void BP_SetBBox(BP_ProxyHandle proxy,
+ const DT_Vector3 min,
+ const DT_Vector3 max);
+
+ extern DECLSPEC void *BP_RayCast(BP_SceneHandle scene,
+ BP_RayCastCallback objectRayCast,
+ void *client_data,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/solid/SOLID/SOLID_types.h b/extern/solid/SOLID/SOLID_types.h
new file mode 100644
index 00000000000..630594e447f
--- /dev/null
+++ b/extern/solid/SOLID/SOLID_types.h
@@ -0,0 +1,53 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_TYPES_H
+#define SOLID_TYPES_H
+
+#ifndef DECLSPEC
+# ifdef WIN32
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+#endif
+
+#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+
+typedef unsigned short DT_Index;
+typedef unsigned short DT_Count;
+typedef unsigned int DT_Size;
+typedef float DT_Scalar;
+typedef int DT_Bool;
+
+#define DT_FALSE 0
+#define DT_TRUE 1
+
+#define DT_CONTINUE 0
+#define DT_DONE 1
+
+typedef DT_Scalar DT_Vector3[3];
+typedef DT_Scalar DT_Quaternion[4];
+
+#endif
diff --git a/extern/solid/VisualC6/broad/broad.dsp b/extern/solid/VisualC6/broad/broad.dsp
new file mode 100644
index 00000000000..1161d68fcd6
--- /dev/null
+++ b/extern/solid/VisualC6/broad/broad.dsp
@@ -0,0 +1,132 @@
+# Microsoft Developer Studio Project File - Name="broad" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=broad - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "broad.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "broad.mak" CFG="broad - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "broad - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "broad - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "broad - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "broad - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "broad - Win32 Release"
+# Name "broad - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\src\broad\BP_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_EndpointList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_Proxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_Scene.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_Endpoint.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_EndpointList.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_Proxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_ProxyList.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\broad\BP_Scene.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/complex/complex.dsp b/extern/solid/VisualC6/complex/complex.dsp
new file mode 100644
index 00000000000..74ea67b9e23
--- /dev/null
+++ b/extern/solid/VisualC6/complex/complex.dsp
@@ -0,0 +1,116 @@
+# Microsoft Developer Studio Project File - Name="complex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=complex - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "complex.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "complex.mak" CFG="complex - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "complex - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "complex - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "complex - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../src/convex" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "complex - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "complex - Win32 Release"
+# Name "complex - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\complex\DT_BBoxTree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\complex\DT_Complex.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\complex\DT_BBoxTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\complex\DT_CBox.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\complex\DT_Complex.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/convex/convex.dsp b/extern/solid/VisualC6/convex/convex.dsp
new file mode 100644
index 00000000000..ec9caace9d9
--- /dev/null
+++ b/extern/solid/VisualC6/convex/convex.dsp
@@ -0,0 +1,232 @@
+# Microsoft Developer Studio Project File - Name="convex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=convex - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "convex.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "convex.mak" CFG="convex - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "convex - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "convex - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "convex - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../../qhull/include" /D "NDEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "convex - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../../qhull/include" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "convex - Win32 Release"
+# Name "convex - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Accuracy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Box.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Cone.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Convex.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Cylinder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Facet.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_LineSegment.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_PenDepth.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Point.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Polyhedron.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Polytope.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Sphere.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Triangle.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Accuracy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Array.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Box.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Cone.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Convex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Cylinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Facet.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_GJK.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Hull.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_IndexArray.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_LineSegment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Minkowski.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_PenDepth.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Point.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Polyhedron.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Polytope.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Shape.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Sphere.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Transform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_Triangle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\convex\DT_VertexBase.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/dynamics/dynamics.dsp b/extern/solid/VisualC6/dynamics/dynamics.dsp
new file mode 100644
index 00000000000..9659cbf8a56
--- /dev/null
+++ b/extern/solid/VisualC6/dynamics/dynamics.dsp
@@ -0,0 +1,120 @@
+# Microsoft Developer Studio Project File - Name="dynamics" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=dynamics - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dynamics.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dynamics.mak" CFG="dynamics - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dynamics - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "dynamics - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dynamics - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "dynamics - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "dynamics - Win32 Release"
+# Name "dynamics - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\Dynamic.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\Kinetic.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\RigidBody.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\Dynamic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\Kinetic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\examples\dynamics\RigidBody.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/gldemo/gldemo.dsp b/extern/solid/VisualC6/gldemo/gldemo.dsp
new file mode 100644
index 00000000000..f3cde286161
--- /dev/null
+++ b/extern/solid/VisualC6/gldemo/gldemo.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="gldemo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gldemo - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gldemo.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gldemo.mak" CFG="gldemo - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gldemo - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gldemo - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gldemo - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "gldemo - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "gldemo - Win32 Release"
+# Name "gldemo - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\examples\gldemo.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/mnm/mnm.dsp b/extern/solid/VisualC6/mnm/mnm.dsp
new file mode 100644
index 00000000000..2df6d951794
--- /dev/null
+++ b/extern/solid/VisualC6/mnm/mnm.dsp
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="mnm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mnm - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mnm.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mnm.mak" CFG="mnm - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mnm - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mnm - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mnm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "mnm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mnm - Win32 Release"
+# Name "mnm - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\examples\mnm.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/physics/physics.dsp b/extern/solid/VisualC6/physics/physics.dsp
new file mode 100644
index 00000000000..dd69b6a35b2
--- /dev/null
+++ b/extern/solid/VisualC6/physics/physics.dsp
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="physics" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=physics - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "physics.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "physics.mak" CFG="physics - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "physics - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "physics - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "physics - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "physics - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "physics - Win32 Release"
+# Name "physics - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\examples\physics.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/sample/sample.dsp b/extern/solid/VisualC6/sample/sample.dsp
new file mode 100644
index 00000000000..c6e0423cd04
--- /dev/null
+++ b/extern/solid/VisualC6/sample/sample.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="sample" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=sample - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sample.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sample.mak" CFG="sample - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sample - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "sample - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sample - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "sample - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "sample - Win32 Release"
+# Name "sample - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\examples\sample.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/solid.dsw b/extern/solid/VisualC6/solid.dsw
new file mode 100644
index 00000000000..397cc4bf371
--- /dev/null
+++ b/extern/solid/VisualC6/solid.dsw
@@ -0,0 +1,89 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "broad"=".\broad\broad.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "complex"=".\complex\complex.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "convex"=".\convex\convex.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name qhull
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "qhull"="..\..\qhull\VisualC6\qhull\qhull.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "solid"=".\solid\solid.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name broad
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name complex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name convex
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extern/solid/VisualC6/solid/solid.dsp b/extern/solid/VisualC6/solid/solid.dsp
new file mode 100644
index 00000000000..4ac7459c2f9
--- /dev/null
+++ b/extern/solid/VisualC6/solid/solid.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="solid" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=solid - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "solid.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "solid.mak" CFG="solid - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "solid - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "solid - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "solid - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "NDEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\lib\windows\solid\include\solid\ XCOPY /Y Release\*.lib ..\..\..\..\..\lib\windows\solid\lib\
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "solid - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=cwlink.exe
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\lib\windows\solid\include\solid\ XCOPY /Y Debug\*.lib ..\..\..\..\..\lib\windows\solid\lib\Debug\
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "solid - Win32 Release"
+# Name "solid - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\src\DT_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Encounter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Object.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_RespTable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Scene.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\DT_AlgoTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Encounter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Response.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_RespTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Scene.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/VisualC6/solid_dll/solid_dll.dsp b/extern/solid/VisualC6/solid_dll/solid_dll.dsp
new file mode 100644
index 00000000000..eed092502e0
--- /dev/null
+++ b/extern/solid/VisualC6/solid_dll/solid_dll.dsp
@@ -0,0 +1,147 @@
+# Microsoft Developer Studio Project File - Name="solid_dll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=solid_dll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "solid_dll.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "solid_dll.mak" CFG="solid_dll - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "solid_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "solid_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "solid_dll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../lib/win32/vc6"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "NDEBUG" /D "USE_DOUBLES" /D "QHULL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../lib/win32/vc6/solid.dll"
+
+!ELSEIF "$(CFG)" == "solid_dll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../lib/win32/vc6"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../lib/win32/vc6/solidd.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "solid_dll - Win32 Release"
+# Name "solid_dll - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\src\DT_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Encounter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Object.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_RespTable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Scene.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\DT_AlgoTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Encounter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Response.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_RespTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\DT_Scene.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/extern/solid/include/GEN_MinMax.h b/extern/solid/include/GEN_MinMax.h
new file mode 100644
index 00000000000..9ea961cfe4f
--- /dev/null
+++ b/extern/solid/include/GEN_MinMax.h
@@ -0,0 +1,76 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef GEN_MINMAX_H
+#define GEN_MINMAX_H
+
+template <class T>
+inline const T& GEN_min(const T& a, const T& b)
+{
+ return b < a ? b : a;
+}
+
+template <class T>
+inline const T& GEN_max(const T& a, const T& b)
+{
+ return a < b ? b : a;
+}
+
+template <class T>
+inline const T& GEN_clamped(const T& a, const T& lb, const T& ub)
+{
+ return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+inline void GEN_set_min(T& a, const T& b)
+{
+ if (b < a)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+inline void GEN_set_max(T& a, const T& b)
+{
+ if (a < b)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+inline void GEN_clamp(T& a, const T& lb, const T& ub)
+{
+ if (a < lb)
+ {
+ a = lb;
+ }
+ else if (ub < a)
+ {
+ a = ub;
+ }
+}
+
+#endif
diff --git a/extern/solid/include/GEN_random.h b/extern/solid/include/GEN_random.h
new file mode 100644
index 00000000000..4690a05511a
--- /dev/null
+++ b/extern/solid/include/GEN_random.h
@@ -0,0 +1,49 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef GEN_RANDOM_H
+#define GEN_RANDOM_H
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define GEN_RAND_MAX UINT_MAX
+
+inline void GEN_srand(unsigned int seed) { init_genrand(seed); }
+inline unsigned int GEN_rand() { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define GEN_RAND_MAX RAND_MAX
+
+inline void GEN_srand(unsigned int seed) { srand(seed); }
+inline unsigned int GEN_rand() { return rand(); }
+
+#endif
+
+#endif
+
diff --git a/extern/solid/include/MT/Interval.h b/extern/solid/include/MT/Interval.h
new file mode 100644
index 00000000000..c6ba2fc1681
--- /dev/null
+++ b/extern/solid/include/MT/Interval.h
@@ -0,0 +1,180 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef INTERVAL_H
+#define INTERVAL_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include <iostream>
+#include <algorithm>
+
+namespace MT {
+
+ template <typename Scalar>
+ class Interval {
+ public:
+ Interval() {}
+
+
+#if _MSC_VER <= 1200
+ explicit Interval(const Scalar& x)
+ : m_lb(x), m_ub(x)
+ {}
+
+
+ Interval(const Scalar& lb, const Scalar& ub)
+ : m_lb(lb), m_ub(ub)
+ {
+ assert(lb <= ub);
+ }
+#else
+ template <typename Scalar2>
+ explicit Interval(const Scalar2& x)
+ : m_lb(x), m_ub(x)
+ {}
+
+ template <typename Scalar2>
+ Interval(const Scalar2& lb, const Scalar2& ub)
+ : m_lb(lb), m_ub(ub)
+ {
+ assert(lb <= ub);
+ }
+
+ template <typename Scalar2>
+ Interval(const Interval<Scalar2>& z)
+ {
+ *this = z;
+ }
+
+ template <typename Scalar2>
+ Interval<Scalar>& operator=(const Interval<Scalar2>& z)
+ {
+ m_lb = Scalar(z.lower());
+ m_ub = Scalar(z.upper());
+ return *this;
+ }
+#endif
+
+
+
+ Scalar& lower() { return m_lb; }
+ const Scalar& lower() const { return m_lb; }
+
+ Scalar& upper() { return m_ub; }
+ const Scalar& upper() const { return m_ub; }
+
+ Scalar center() const { return (m_lb + m_ub) * Scalar(0.5); }
+ Scalar extent() const { return (m_ub - m_lb) * Scalar(0.5); }
+
+
+ protected:
+ Scalar m_lb, m_ub;
+ };
+
+ template <typename Scalar>
+ inline Interval<Scalar>
+ operator+(const Interval<Scalar>& z1, const Interval<Scalar>& z2)
+ {
+ return Interval<Scalar>(z1.lower() + z2.lower(),
+ z1.upper() + z2.upper());
+ }
+
+ template <typename Scalar>
+ inline Interval<Scalar>
+ operator-(const Interval<Scalar>& z1, const Interval<Scalar>& z2)
+ {
+ return Interval<Scalar>(z1.lower() - z2.upper(),
+ z1.upper() - z2.lower());
+ }
+
+ template <typename Scalar>
+ inline std::ostream&
+ operator<<(std::ostream& os, const Interval<Scalar>& z)
+ {
+ return os << '[' << z.lower() << ", " << z.upper() << ']';
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ median(const Interval<Scalar>& z)
+ {
+ return (z.lower() + z.upper()) * Scalar(0.5);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ width(const Interval<Scalar>& z)
+ {
+ return z.upper() - z.lower();
+ }
+
+ template <typename Scalar>
+ inline bool
+ overlap(const Interval<Scalar>& z1, const Interval<Scalar>& z2)
+ {
+ return z1.lower() <= z2.upper() && z2.lower() <= z1.upper();
+ }
+
+ template <typename Scalar>
+ inline bool
+ in(const Interval<Scalar>& z1, const Interval<Scalar>& z2)
+ {
+ return z2.lower() <= z1.lower() && z1.upper() <= z2.upper();
+ }
+
+ template <typename Scalar>
+ inline bool
+ in(Scalar x, const Interval<Scalar>& z)
+ {
+ return z.lower() <= x && x <= z.upper();
+ }
+
+ template <typename Scalar>
+ inline Interval<Scalar>
+ widen(const Interval<Scalar>& z, const Scalar& x)
+ {
+ return Interval<Scalar>(z.lower() - x, z.upper() + x);
+ }
+
+ template<typename Scalar>
+ inline Interval<Scalar>
+ hull(const Interval<Scalar>& z1, const Interval<Scalar>& z2)
+ {
+ return Interval<Scalar>(GEN_min(z1.lower(), z2.lower()),
+ GEN_max(z1.upper(), z2.upper()));
+ }
+
+ template<typename Scalar>
+ inline Interval<Scalar>
+ operator+(Scalar x, const Interval<Scalar>& z)
+ {
+ return Interval<Scalar>(x + z.lower(), x + z.upper());
+ }
+}
+
+#endif
diff --git a/extern/solid/include/MT/Matrix3x3.h b/extern/solid/include/MT/Matrix3x3.h
new file mode 100644
index 00000000000..85e0d4cac84
--- /dev/null
+++ b/extern/solid/include/MT/Matrix3x3.h
@@ -0,0 +1,380 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MATRIX3X3_H
+#define MATRIX3X3_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include "Vector3.h"
+#include "Quaternion.h"
+
+namespace MT {
+
+ // Row-major 3x3 matrix
+
+ template <typename Scalar>
+ class Matrix3x3 {
+ public:
+ Matrix3x3() {}
+
+ template <typename Scalar2>
+ explicit Matrix3x3(const Scalar2 *m) { setValue(m); }
+
+ explicit Matrix3x3(const Quaternion<Scalar>& q) { setRotation(q); }
+
+ template <typename Scalar2>
+ Matrix3x3(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
+ {
+ setEuler(yaw, pitch, roll);
+ }
+
+ template <typename Scalar2>
+ Matrix3x3(const Scalar2& xx, const Scalar2& xy, const Scalar2& xz,
+ const Scalar2& yx, const Scalar2& yy, const Scalar2& yz,
+ const Scalar2& zx, const Scalar2& zy, const Scalar2& zz)
+ {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
+ }
+
+ Vector3<Scalar>& operator[](int i)
+ {
+ assert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ const Vector3<Scalar>& operator[](int i) const
+ {
+ assert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ Matrix3x3<Scalar>& operator*=(const Matrix3x3<Scalar>& m);
+
+ template <typename Scalar2>
+ void setValue(const Scalar2 *m)
+ {
+ m_el[0][0] = Scalar(m[0]);
+ m_el[1][0] = Scalar(m[1]);
+ m_el[2][0] = Scalar(m[2]);
+ m_el[0][1] = Scalar(m[4]);
+ m_el[1][1] = Scalar(m[5]);
+ m_el[2][1] = Scalar(m[6]);
+ m_el[0][2] = Scalar(m[8]);
+ m_el[1][2] = Scalar(m[9]);
+ m_el[2][2] = Scalar(m[10]);
+ }
+
+ template <typename Scalar2>
+ void setValue(const Scalar2& xx, const Scalar2& xy, const Scalar2& xz,
+ const Scalar2& yx, const Scalar2& yy, const Scalar2& yz,
+ const Scalar2& zx, const Scalar2& zy, const Scalar2& zz)
+ {
+ m_el[0][0] = Scalar(xx);
+ m_el[0][1] = Scalar(xy);
+ m_el[0][2] = Scalar(xz);
+ m_el[1][0] = Scalar(yx);
+ m_el[1][1] = Scalar(yy);
+ m_el[1][2] = Scalar(yz);
+ m_el[2][0] = Scalar(zx);
+ m_el[2][1] = Scalar(zy);
+ m_el[2][2] = Scalar(zz);
+ }
+
+ void setRotation(const Quaternion<Scalar>& q)
+ {
+ Scalar d = q.length2();
+ assert(d != Scalar(0.0));
+ Scalar s = Scalar(2.0) / d;
+ Scalar xs = q[0] * s, ys = q[1] * s, zs = q[2] * s;
+ Scalar wx = q[3] * xs, wy = q[3] * ys, wz = q[3] * zs;
+ Scalar xx = q[0] * xs, xy = q[0] * ys, xz = q[0] * zs;
+ Scalar yy = q[1] * ys, yz = q[1] * zs, zz = q[2] * zs;
+ setValue(Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ xy + wz, Scalar(1.0) - (xx + zz), yz - wx,
+ xz - wy, yz + wx, Scalar(1.0) - (xx + yy));
+ }
+
+ template <typename Scalar2>
+ void setEuler(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
+ {
+ Scalar cy(Scalar_traits<Scalar>::cos(yaw));
+ Scalar sy(Scalar_traits<Scalar>::sin(yaw));
+ Scalar cp(Scalar_traits<Scalar>::cos(pitch));
+ Scalar sp(Scalar_traits<Scalar>::sin(pitch));
+ Scalar cr(Scalar_traits<Scalar>::cos(roll));
+ Scalar sr(Scalar_traits<Scalar>::sin(roll));
+ Scalar cc = cy * cr;
+ Scalar cs = cy * sr;
+ Scalar sc = sy * cr;
+ Scalar ss = sy * sr;
+ setValue(cy * cp, -sc + sp * cs, ss - sp * cc,
+ sy * cp, cc + sp * ss, -cs + sp * sc,
+ -sp, cp * sr, cp * cr);
+ }
+ void setIdentity()
+ {
+ setValue(Scalar(1.0), Scalar(0.0), Scalar(0.0),
+ Scalar(0.0), Scalar(1.0), Scalar(0.0),
+ Scalar(0.0), Scalar(0.0), Scalar(1.0));
+ }
+
+ template <typename Scalar2>
+ void getValue(Scalar2 *m) const
+ {
+ m[0] = Scalar2(m_el[0][0]);
+ m[1] = Scalar2(m_el[1][0]);
+ m[2] = Scalar2(m_el[2][0]);
+ m[3] = Scalar2(0.0);
+ m[4] = Scalar2(m_el[0][1]);
+ m[5] = Scalar2(m_el[1][1]);
+ m[6] = Scalar2(m_el[2][1]);
+ m[7] = Scalar2(0.0);
+ m[8] = Scalar2(m_el[0][2]);
+ m[9] = Scalar2(m_el[1][2]);
+ m[10] = Scalar2(m_el[2][2]);
+ m[11] = Scalar2(0.0);
+ }
+
+ void getRotation(Quaternion<Scalar>& q) const
+ {
+ Scalar trace = m_el[0][0] + m_el[1][1] + m_el[2][2];
+
+ if (trace > Scalar(0.0))
+ {
+ Scalar s = Scalar_traits<Scalar>::sqrt(trace + Scalar(1.0));
+ q[3] = s * Scalar(0.5);
+ s = Scalar(0.5) / s;
+
+ q[0] = (m_el[2][1] - m_el[1][2]) * s;
+ q[1] = (m_el[0][2] - m_el[2][0]) * s;
+ q[2] = (m_el[1][0] - m_el[0][1]) * s;
+ }
+ else
+ {
+ int i = m_el[0][0] < m_el[1][1] ?
+ (m_el[1][1] < m_el[2][2] ? 2 : 1) :
+ (m_el[0][0] < m_el[2][2] ? 2 : 0);
+ int j = (i + 1) % 3;
+ int k = (i + 2) % 3;
+
+ Scalar s = Scalar_traits<Scalar>::sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + Scalar(1.0));
+ q[i] = s * Scalar(0.5);
+ s = Scalar(0.5) / s;
+
+ q[3] = (m_el[k][j] - m_el[j][k]) * s;
+ q[j] = (m_el[j][i] + m_el[i][j]) * s;
+ q[k] = (m_el[k][i] + m_el[i][k]) * s;
+ }
+ }
+
+
+
+ template <typename Scalar2>
+ void getEuler(Scalar2& yaw, Scalar2& pitch, Scalar2& roll) const
+ {
+ pitch = Scalar2(Scalar_traits<Scalar>::asin(-m_el[2][0]));
+ if (pitch < Scalar_traits<Scalar2>::TwoTimesPi())
+ {
+ if (pitch > Scalar_traits<Scalar2>::TwoTimesPi())
+ {
+ yaw = Scalar2(Scalar_traits<Scalar>::atan2(m_el[1][0], m_el[0][0]));
+ roll = Scalar2(Scalar_traits<Scalar>::atan2(m_el[2][1], m_el[2][2]));
+ }
+ else
+ {
+ yaw = Scalar2(-Scalar_traits<Scalar>::atan2(-m_el[0][1], m_el[0][2]));
+ roll = Scalar2(0.0);
+ }
+ }
+ else
+ {
+ yaw = Scalar2(Scalar_traits<Scalar>::atan2(-m_el[0][1], m_el[0][2]));
+ roll = Scalar2(0.0);
+ }
+ }
+
+ Vector3<Scalar> getScaling() const
+ {
+ return Vector3<Scalar>(m_el[0][0] * m_el[0][0] + m_el[1][0] * m_el[1][0] + m_el[2][0] * m_el[2][0],
+ m_el[0][1] * m_el[0][1] + m_el[1][1] * m_el[1][1] + m_el[2][1] * m_el[2][1],
+ m_el[0][2] * m_el[0][2] + m_el[1][2] * m_el[1][2] + m_el[2][2] * m_el[2][2]);
+ }
+
+
+ Matrix3x3<Scalar> scaled(const Vector3<Scalar>& s) const
+ {
+ return Matrix3x3<Scalar>(m_el[0][0] * s[0], m_el[0][1] * s[1], m_el[0][2] * s[2],
+ m_el[1][0] * s[0], m_el[1][1] * s[1], m_el[1][2] * s[2],
+ m_el[2][0] * s[0], m_el[2][1] * s[1], m_el[2][2] * s[2]);
+ }
+
+ Scalar determinant() const;
+ Matrix3x3<Scalar> adjoint() const;
+ Matrix3x3<Scalar> absolute() const;
+ Matrix3x3<Scalar> transpose() const;
+ Matrix3x3<Scalar> inverse() const;
+
+ Matrix3x3<Scalar> transposeTimes(const Matrix3x3<Scalar>& m) const;
+ Matrix3x3<Scalar> timesTranspose(const Matrix3x3<Scalar>& m) const;
+
+ Scalar tdot(int c, const Vector3<Scalar>& v) const
+ {
+ return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2];
+ }
+
+ protected:
+ Scalar cofac(int r1, int c1, int r2, int c2) const
+ {
+ return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+ }
+
+ Vector3<Scalar> m_el[3];
+ };
+
+ template <typename Scalar>
+ inline std::ostream&
+ operator<<(std::ostream& os, const Matrix3x3<Scalar>& m)
+ {
+ return os << m[0] << std::endl << m[1] << std::endl << m[2] << std::endl;
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>&
+ Matrix3x3<Scalar>::operator*=(const Matrix3x3<Scalar>& m)
+ {
+ setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]),
+ m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]),
+ m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]));
+ return *this;
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ Matrix3x3<Scalar>::determinant() const
+ {
+ return triple((*this)[0], (*this)[1], (*this)[2]);
+ }
+
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::absolute() const
+ {
+ return Matrix3x3<Scalar>(
+ Scalar_traits<Scalar>::abs(m_el[0][0]), Scalar_traits<Scalar>::abs(m_el[0][1]), Scalar_traits<Scalar>::abs(m_el[0][2]),
+ Scalar_traits<Scalar>::abs(m_el[1][0]), Scalar_traits<Scalar>::abs(m_el[1][1]), Scalar_traits<Scalar>::abs(m_el[1][2]),
+ Scalar_traits<Scalar>::abs(m_el[2][0]), Scalar_traits<Scalar>::abs(m_el[2][1]), Scalar_traits<Scalar>::abs(m_el[2][2]));
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::transpose() const
+ {
+ return Matrix3x3<Scalar>(m_el[0][0], m_el[1][0], m_el[2][0],
+ m_el[0][1], m_el[1][1], m_el[2][1],
+ m_el[0][2], m_el[1][2], m_el[2][2]);
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::adjoint() const
+ {
+ return Matrix3x3<Scalar>(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::inverse() const
+ {
+ Vector3<Scalar> co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+ Scalar det = (*this)[0].dot(co);
+ assert(det != Scalar(0.0));
+ Scalar s = Scalar(1.0) / det;
+ return Matrix3x3<Scalar>(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+ co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::transposeTimes(const Matrix3x3<Scalar>& m) const
+ {
+ return Matrix3x3<Scalar>(
+ m_el[0][0] * m[0][0] + m_el[1][0] * m[1][0] + m_el[2][0] * m[2][0],
+ m_el[0][0] * m[0][1] + m_el[1][0] * m[1][1] + m_el[2][0] * m[2][1],
+ m_el[0][0] * m[0][2] + m_el[1][0] * m[1][2] + m_el[2][0] * m[2][2],
+ m_el[0][1] * m[0][0] + m_el[1][1] * m[1][0] + m_el[2][1] * m[2][0],
+ m_el[0][1] * m[0][1] + m_el[1][1] * m[1][1] + m_el[2][1] * m[2][1],
+ m_el[0][1] * m[0][2] + m_el[1][1] * m[1][2] + m_el[2][1] * m[2][2],
+ m_el[0][2] * m[0][0] + m_el[1][2] * m[1][0] + m_el[2][2] * m[2][0],
+ m_el[0][2] * m[0][1] + m_el[1][2] * m[1][1] + m_el[2][2] * m[2][1],
+ m_el[0][2] * m[0][2] + m_el[1][2] * m[1][2] + m_el[2][2] * m[2][2]);
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ Matrix3x3<Scalar>::timesTranspose(const Matrix3x3<Scalar>& m) const
+ {
+ return Matrix3x3<Scalar>(
+ m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+ m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+ m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator*(const Matrix3x3<Scalar>& m, const Vector3<Scalar>& v)
+ {
+ return Vector3<Scalar>(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+ }
+
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator*(const Vector3<Scalar>& v, const Matrix3x3<Scalar>& m)
+ {
+ return Vector3<Scalar>(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v));
+ }
+
+ template <typename Scalar>
+ inline Matrix3x3<Scalar>
+ operator*(const Matrix3x3<Scalar>& m1, const Matrix3x3<Scalar>& m2)
+ {
+ return Matrix3x3<Scalar>(
+ m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]),
+ m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]),
+ m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]));
+ }
+}
+
+#endif
diff --git a/extern/solid/include/MT/Quaternion.h b/extern/solid/include/MT/Quaternion.h
new file mode 100644
index 00000000000..a925f21cd5d
--- /dev/null
+++ b/extern/solid/include/MT/Quaternion.h
@@ -0,0 +1,316 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef QUATERNION_H
+#define QUATERNION_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include "Tuple4.h"
+#include "Vector3.h"
+
+namespace MT {
+
+ template <typename Scalar>
+ class Quaternion : public Tuple4<Scalar> {
+ public:
+ Quaternion() {}
+
+ template <typename Scalar2>
+ explicit Quaternion(const Scalar2 *v) : Tuple4<Scalar>(v) {}
+
+ template <typename Scalar2>
+ Quaternion(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w)
+ : Tuple4<Scalar>(x, y, z, w)
+ {}
+
+ Quaternion(const Vector3<Scalar>& axis, const Scalar& angle)
+ {
+ setRotation(axis, angle);
+ }
+
+ template <typename Scalar2>
+ Quaternion(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
+ {
+ setEuler(yaw, pitch, roll);
+ }
+
+ void setRotation(const Vector3<Scalar>& axis, const Scalar& angle)
+ {
+ Scalar d = axis.length();
+ assert(d != Scalar(0.0));
+ Scalar s = Scalar_traits<Scalar>::sin(angle * Scalar(0.5)) / d;
+ setValue(axis[0] * s, axis[1] * s, axis[2] * s,
+ Scalar_traits<Scalar>::cos(angle * Scalar(0.5)));
+ }
+
+ template <typename Scalar2>
+ void setEuler(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
+ {
+ Scalar halfYaw = Scalar(yaw) * Scalar(0.5);
+ Scalar halfPitch = Scalar(pitch) * Scalar(0.5);
+ Scalar halfRoll = Scalar(roll) * Scalar(0.5);
+ Scalar cosYaw = Scalar_traits<Scalar>::cos(halfYaw);
+ Scalar sinYaw = Scalar_traits<Scalar>::sin(halfYaw);
+ Scalar cosPitch = Scalar_traits<Scalar>::cos(halfPitch);
+ Scalar sinPitch = Scalar_traits<Scalar>::sin(halfPitch);
+ Scalar cosRoll = Scalar_traits<Scalar>::cos(halfRoll);
+ Scalar sinRoll = Scalar_traits<Scalar>::sin(halfRoll);
+ setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ }
+
+ Quaternion<Scalar>& operator+=(const Quaternion<Scalar>& q)
+ {
+ this->m_co[0] += q[0]; this->m_co[1] += q[1]; this->m_co[2] += q[2]; this->m_co[3] += q[3];
+ return *this;
+ }
+
+ Quaternion<Scalar>& operator-=(const Quaternion<Scalar>& q)
+ {
+ this->m_co[0] -= q[0]; this->m_co[1] -= q[1]; this->m_co[2] -= q[2]; this->m_co[3] -= q[3];
+ return *this;
+ }
+
+ Quaternion<Scalar>& operator*=(const Scalar& s)
+ {
+ this->m_co[0] *= s; this->m_co[1] *= s; this->m_co[2] *= s; this->m_co[3] *= s;
+ return *this;
+ }
+
+ Quaternion<Scalar>& operator/=(const Scalar& s)
+ {
+ assert(s != Scalar(0.0));
+ return *this *= Scalar(1.0) / s;
+ }
+
+ Quaternion<Scalar>& operator*=(const Quaternion<Scalar>& q)
+ {
+ setValue(this->m_co[3] * q[0] + this->m_co[0] * q[3] + this->m_co[1] * q[2] - this->m_co[2] * q[1],
+ this->m_co[3] * q[1] + this->m_co[1] * q[3] + this->m_co[2] * q[0] - this->m_co[0] * q[2],
+ this->m_co[3] * q[2] + this->m_co[2] * q[3] + this->m_co[0] * q[1] - this->m_co[1] * q[0],
+ this->m_co[3] * q[3] - this->m_co[0] * q[0] - this->m_co[1] * q[1] - this->m_co[2] * q[2]);
+ return *this;
+ }
+
+ Scalar dot(const Quaternion<Scalar>& q) const
+ {
+ return this->m_co[0] * q[0] + this->m_co[1] * q[1] + this->m_co[2] * q[2] + this->m_co[3] * q[3];
+ }
+
+ Scalar length2() const
+ {
+ return dot(*this);
+ }
+
+ Scalar length() const
+ {
+ return Scalar_traits<Scalar>::sqrt(length2());
+ }
+
+ Quaternion<Scalar>& normalize()
+ {
+ return *this /= length();
+ }
+
+ Quaternion<Scalar> normalized() const
+ {
+ return *this / length();
+ }
+
+ Scalar angle(const Quaternion<Scalar>& q) const
+ {
+ Scalar s = Scalar_traits<Scalar>::sqrt(length2() * q.length2());
+ assert(s != Scalar(0.0));
+ return Scalar_traits<Scalar>::acos(dot(q) / s);
+ }
+
+ Quaternion<Scalar> conjugate() const
+ {
+ return Quaternion<Scalar>(-this->m_co[0], -this->m_co[1], -this->m_co[2], this->m_co[3]);
+ }
+
+ Quaternion<Scalar> inverse() const
+ {
+ return conjugate / length2();
+ }
+
+ Quaternion<Scalar> slerp(const Quaternion<Scalar>& q, const Scalar& t) const
+ {
+ Scalar theta = angle(q);
+ if (theta != Scalar(0.0))
+ {
+ Scalar d = Scalar(1.0) / Scalar_traits<Scalar>::sin(theta);
+ Scalar s0 = Scalar_traits<Scalar>::sin((Scalar(1.0) - t) * theta);
+ Scalar s1 = Scalar_traits<Scalar>::sin(t * theta);
+ return Quaternion<Scalar>((this->m_co[0] * s0 + q[0] * s1) * d,
+ (this->m_co[1] * s0 + q[1] * s1) * d,
+ (this->m_co[2] * s0 + q[2] * s1) * d,
+ (this->m_co[3] * s0 + q[3] * s1) * d);
+ }
+ else
+ {
+ return *this;
+ }
+ }
+
+ static Quaternion<Scalar> random()
+ {
+ // From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
+ // pg. 124-132
+ Scalar x0 = Scalar_traits<Scalar>::random();
+ Scalar r1 = Scalar_traits<Scalar>::sqrt(Scalar(1.0) - x0);
+ Scalar r2 = Scalar_traits<Scalar>::sqrt(x0);
+ Scalar t1 = Scalar_traits<Scalar>::TwoTimesPi() * Scalar_traits<Scalar>::random();
+ Scalar t2 = Scalar_traits<Scalar>::TwoTimesPi() * Scalar_traits<Scalar>::random();
+ Scalar c1 = Scalar_traits<Scalar>::cos(t1);
+ Scalar s1 = Scalar_traits<Scalar>::sin(t1);
+ Scalar c2 = Scalar_traits<Scalar>::cos(t2);
+ Scalar s2 = Scalar_traits<Scalar>::sin(t2);
+ return Quaternion<Scalar>(s1 * r1, c1 * r1, s2 * r2, c2 * r2);
+ }
+
+ };
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator+(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2)
+ {
+ return Quaternion<Scalar>(q1[0] + q2[0], q1[1] + q2[1], q1[2] + q2[2], q1[3] + q2[3]);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator-(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2)
+ {
+ return Quaternion<Scalar>(q1[0] - q2[0], q1[1] - q2[1], q1[2] - q2[2], q1[3] - q2[3]);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator-(const Quaternion<Scalar>& q)
+ {
+ return Quaternion<Scalar>(-q[0], -q[1], -q[2], -q[3]);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator*(const Quaternion<Scalar>& q, const Scalar& s)
+ {
+ return Quaternion<Scalar>(q[0] * s, q[1] * s, q[2] * s, q[3] * s);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator*(const Scalar& s, const Quaternion<Scalar>& q)
+ {
+ return q * s;
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator*(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2) {
+ return Quaternion<Scalar>(q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1],
+ q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2],
+ q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0],
+ q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator*(const Quaternion<Scalar>& q, const Vector3<Scalar>& w)
+ {
+ return Quaternion<Scalar>( q[3] * w[0] + q[1] * w[2] - q[2] * w[1],
+ q[3] * w[1] + q[2] * w[0] - q[0] * w[2],
+ q[3] * w[2] + q[0] * w[1] - q[1] * w[0],
+ -q[0] * w[0] - q[1] * w[1] - q[2] * w[2]);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ operator*(const Vector3<Scalar>& w, const Quaternion<Scalar>& q)
+ {
+ return Quaternion<Scalar>( w[0] * q[3] + w[1] * q[2] - w[2] * q[1],
+ w[1] * q[3] + w[2] * q[0] - w[0] * q[2],
+ w[2] * q[3] + w[0] * q[1] - w[1] * q[0],
+ -w[0] * q[0] - w[1] * q[1] - w[2] * q[2]);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ dot(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2)
+ {
+ return q1.dot(q2);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ length2(const Quaternion<Scalar>& q)
+ {
+ return q.length2();
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ length(const Quaternion<Scalar>& q)
+ {
+ return q.length();
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ angle(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2)
+ {
+ return q1.angle(q2);
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ conjugate(const Quaternion<Scalar>& q)
+ {
+ return q.conjugate();
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ inverse(const Quaternion<Scalar>& q)
+ {
+ return q.inverse();
+ }
+
+ template <typename Scalar>
+ inline Quaternion<Scalar>
+ slerp(const Quaternion<Scalar>& q1, const Quaternion<Scalar>& q2, const Scalar& t)
+ {
+ return q1.slerp(q2, t);
+ }
+
+}
+
+#endif
diff --git a/extern/solid/include/MT/Transform.h b/extern/solid/include/MT/Transform.h
new file mode 100644
index 00000000000..b80dc1bc18b
--- /dev/null
+++ b/extern/solid/include/MT/Transform.h
@@ -0,0 +1,189 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "Vector3.h"
+#include "Matrix3x3.h"
+
+namespace MT {
+
+ template <typename Scalar>
+ class Transform {
+ enum {
+ TRANSLATION = 0x01,
+ ROTATION = 0x02,
+ RIGID = TRANSLATION | ROTATION,
+ SCALING = 0x04,
+ LINEAR = ROTATION | SCALING,
+ AFFINE = TRANSLATION | LINEAR
+ };
+
+ public:
+ Transform() {}
+
+ template <typename Scalar2>
+ explicit Transform(const Scalar2 *m) { setValue(m); }
+
+ explicit Transform(const Quaternion<Scalar>& q,
+ const Vector3<Scalar>& c = Vector3<Scalar>(Scalar(0), Scalar(0), Scalar(0)))
+ : m_basis(q),
+ m_origin(c),
+ m_type(RIGID)
+ {}
+
+ explicit Transform(const Matrix3x3<Scalar>& b,
+ const Vector3<Scalar>& c = Vector3<Scalar>(Scalar(0), Scalar(0), Scalar(0)),
+ unsigned int type = AFFINE)
+ : m_basis(b),
+ m_origin(c),
+ m_type(type)
+ {}
+
+ Vector3<Scalar> operator()(const Vector3<Scalar>& x) const
+ {
+ return Vector3<Scalar>(m_basis[0].dot(x) + m_origin[0],
+ m_basis[1].dot(x) + m_origin[1],
+ m_basis[2].dot(x) + m_origin[2]);
+ }
+
+ Vector3<Scalar> operator*(const Vector3<Scalar>& x) const
+ {
+ return (*this)(x);
+ }
+
+ Matrix3x3<Scalar>& getBasis() { return m_basis; }
+ const Matrix3x3<Scalar>& getBasis() const { return m_basis; }
+
+ Vector3<Scalar>& getOrigin() { return m_origin; }
+ const Vector3<Scalar>& getOrigin() const { return m_origin; }
+
+ Quaternion<Scalar> getRotation() const { return m_basis.getRotation(); }
+ template <typename Scalar2>
+ void setValue(const Scalar2 *m)
+ {
+ m_basis.setValue(m);
+ m_origin.setValue(&m[12]);
+ m_type = AFFINE;
+ }
+
+ template <typename Scalar2>
+ void getValue(Scalar2 *m) const
+ {
+ m_basis.getValue(m);
+ m_origin.getValue(&m[12]);
+ m[15] = Scalar2(1.0);
+ }
+
+ void setOrigin(const Vector3<Scalar>& origin)
+ {
+ m_origin = origin;
+ m_type |= TRANSLATION;
+ }
+
+ void setBasis(const Matrix3x3<Scalar>& basis)
+ {
+ m_basis = basis;
+ m_type |= LINEAR;
+ }
+
+ void setRotation(const Quaternion<Scalar>& q)
+ {
+ m_basis.setRotation(q);
+ m_type = (m_type & ~LINEAR) | ROTATION;
+ }
+
+ void scale(const Vector3<Scalar>& scaling)
+ {
+ m_basis = m_basis.scaled(scaling);
+ m_type |= SCALING;
+ }
+
+ void setIdentity()
+ {
+ m_basis.setIdentity();
+ m_origin.setValue(Scalar(0.0), Scalar(0.0), Scalar(0.0));
+ m_type = 0x0;
+ }
+
+ bool isIdentity() const { return m_type == 0x0; }
+
+ Transform<Scalar>& operator*=(const Transform<Scalar>& t)
+ {
+ m_origin += m_basis * t.m_origin;
+ m_basis *= t.m_basis;
+ m_type |= t.m_type;
+ return *this;
+ }
+
+ Transform<Scalar> inverse() const
+ {
+ Matrix3x3<Scalar> inv = (m_type & SCALING) ?
+ m_basis.inverse() :
+ m_basis.transpose();
+
+ return Transform<Scalar>(inv, inv * -m_origin, m_type);
+ }
+
+ Transform<Scalar> inverseTimes(const Transform<Scalar>& t) const;
+
+ Transform<Scalar> operator*(const Transform<Scalar>& t) const;
+
+ private:
+
+ Matrix3x3<Scalar> m_basis;
+ Vector3<Scalar> m_origin;
+ unsigned int m_type;
+ };
+
+
+ template <typename Scalar>
+ inline Transform<Scalar>
+ Transform<Scalar>::inverseTimes(const Transform<Scalar>& t) const
+ {
+ Vector3<Scalar> v = t.getOrigin() - m_origin;
+ if (m_type & SCALING)
+ {
+ Matrix3x3<Scalar> inv = m_basis.inverse();
+ return Transform<Scalar>(inv * t.getBasis(), inv * v,
+ m_type | t.m_type);
+ }
+ else
+ {
+ return Transform<Scalar>(m_basis.transposeTimes(t.m_basis),
+ v * m_basis, m_type | t.m_type);
+ }
+ }
+
+ template <typename Scalar>
+ inline Transform<Scalar>
+ Transform<Scalar>::operator*(const Transform<Scalar>& t) const
+ {
+ return Transform<Scalar>(m_basis * t.m_basis,
+ (*this)(t.m_origin),
+ m_type | t.m_type);
+ }
+}
+
+#endif
diff --git a/extern/solid/include/MT/Tuple3.h b/extern/solid/include/MT/Tuple3.h
new file mode 100644
index 00000000000..52ea33b7f58
--- /dev/null
+++ b/extern/solid/include/MT/Tuple3.h
@@ -0,0 +1,120 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef TUPLE3_H
+#define TUPLE3_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include <iostream>
+
+namespace MT {
+
+ template <typename Scalar>
+ class Tuple3 {
+ public:
+ Tuple3() {}
+
+ template <typename Scalar2>
+ explicit Tuple3(const Scalar2 *v)
+ {
+ setValue(v);
+ }
+
+ template <typename Scalar2>
+ Tuple3(const Scalar2& x, const Scalar2& y, const Scalar2& z)
+ {
+ setValue(x, y, z);
+ }
+
+ template <typename Scalar2>
+ Tuple3(const Tuple3<Scalar2>& t)
+ {
+ *this = t;
+ }
+
+ template <typename Scalar2>
+ Tuple3<Scalar>& operator=(const Tuple3<Scalar2>& t)
+ {
+ m_co[0] = Scalar(t[0]);
+ m_co[1] = Scalar(t[1]);
+ m_co[2] = Scalar(t[2]);
+ return *this;
+ }
+
+ operator Scalar *() { return m_co; }
+ operator const Scalar *() const { return m_co; }
+
+ Scalar& operator[](int i) { return m_co[i]; }
+ const Scalar& operator[](int i) const { return m_co[i]; }
+
+ Scalar& x() { return m_co[0]; }
+ const Scalar& x() const { return m_co[0]; }
+
+ Scalar& y() { return m_co[1]; }
+ const Scalar& y() const { return m_co[1]; }
+
+ Scalar& z() { return m_co[2]; }
+ const Scalar& z() const { return m_co[2]; }
+
+ template <typename Scalar2>
+ void setValue(const Scalar2 *v)
+ {
+ m_co[0] = Scalar(v[0]);
+ m_co[1] = Scalar(v[1]);
+ m_co[2] = Scalar(v[2]);
+ }
+
+ template <typename Scalar2>
+ void setValue(const Scalar2& x, const Scalar2& y, const Scalar2& z)
+ {
+ m_co[0] = Scalar(x);
+ m_co[1] = Scalar(y);
+ m_co[2] = Scalar(z);
+ }
+
+ template <typename Scalar2>
+ void getValue(Scalar2 *v) const
+ {
+ v[0] = Scalar2(m_co[0]);
+ v[1] = Scalar2(m_co[1]);
+ v[2] = Scalar2(m_co[2]);
+ }
+
+ protected:
+ Scalar m_co[3];
+ };
+
+ template <typename Scalar>
+ inline std::ostream&
+ operator<<(std::ostream& os, const Tuple3<Scalar>& t)
+ {
+ return os << t[0] << ' ' << t[1] << ' ' << t[2];
+ }
+}
+
+#endif
diff --git a/extern/solid/include/MT/Tuple4.h b/extern/solid/include/MT/Tuple4.h
new file mode 100644
index 00000000000..6930541271e
--- /dev/null
+++ b/extern/solid/include/MT/Tuple4.h
@@ -0,0 +1,112 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef TUPLE4_H
+#define TUPLE4_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include <iostream>
+
+namespace MT {
+
+ template <typename Scalar>
+ class Tuple4 {
+ public:
+ Tuple4() {}
+
+ template <typename Scalar2>
+ explicit Tuple4(const Scalar2 *v)
+ {
+ setValue(v);
+ }
+
+ template <typename Scalar2>
+ Tuple4(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w)
+ {
+ setValue(x, y, z, w);
+ }
+
+ operator Scalar *() { return m_co; }
+ operator const Scalar *() const { return m_co; }
+
+ Scalar& operator[](int i) { return m_co[i]; }
+ const Scalar& operator[](int i) const { return m_co[i]; }
+
+ Scalar& x() { return m_co[0]; }
+ const Scalar& x() const { return m_co[0]; }
+
+ Scalar& y() { return m_co[1]; }
+ const Scalar& y() const { return m_co[1]; }
+
+ Scalar& z() { return m_co[2]; }
+ const Scalar& z() const { return m_co[2]; }
+
+ Scalar& w() { return m_co[3]; }
+ const Scalar& w() const { return m_co[3]; }
+
+ template <typename Scalar2>
+ void setValue(const Scalar2 *v)
+ {
+ m_co[0] = Scalar(v[0]);
+ m_co[1] = Scalar(v[1]);
+ m_co[2] = Scalar(v[2]);
+ m_co[3] = Scalar(v[3]);
+ }
+
+ template <typename Scalar2>
+ void setValue(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w)
+ {
+ m_co[0] = Scalar(x);
+ m_co[1] = Scalar(y);
+ m_co[2] = Scalar(z);
+ m_co[3] = Scalar(w);
+ }
+
+ template <typename Scalar2>
+ void getValue(Scalar2 *v) const
+ {
+ v[0] = Scalar2(m_co[0]);
+ v[1] = Scalar2(m_co[1]);
+ v[2] = Scalar2(m_co[2]);
+ v[3] = Scalar2(m_co[3]);
+ }
+
+ protected:
+ Scalar m_co[4];
+ };
+
+ template <typename Scalar>
+ inline std::ostream&
+ operator<<(std::ostream& os, const Tuple4<Scalar>& t)
+ {
+ return os << t[0] << ' ' << t[1] << ' ' << t[2] << ' ' << t[3];
+ }
+
+}
+
+#endif
diff --git a/extern/solid/include/MT/Vector3.h b/extern/solid/include/MT/Vector3.h
new file mode 100644
index 00000000000..b569c003f59
--- /dev/null
+++ b/extern/solid/include/MT/Vector3.h
@@ -0,0 +1,283 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef VECTOR3_H
+#define VECTOR3_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+#include "Tuple3.h"
+
+namespace MT {
+
+ template <typename Scalar>
+ class Vector3 : public Tuple3<Scalar> {
+ public:
+ Vector3() {}
+
+ template <typename Scalar2>
+ explicit Vector3(const Scalar2 *v) : Tuple3<Scalar>(v) {}
+
+ template <typename Scalar2>
+ Vector3(const Scalar2& x, const Scalar2& y, const Scalar2& z)
+ : Tuple3<Scalar>(x, y, z)
+ {}
+
+ Vector3<Scalar>& operator+=(const Vector3<Scalar>& v)
+ {
+ this->m_co[0] += v[0]; this->m_co[1] += v[1]; this->m_co[2] += v[2];
+ return *this;
+ }
+
+ Vector3<Scalar>& operator-=(const Vector3<Scalar>& v)
+ {
+ this->m_co[0] -= v[0]; this->m_co[1] -= v[1]; this->m_co[2] -= v[2];
+ return *this;
+ }
+
+ Vector3<Scalar>& operator*=(const Scalar& s)
+ {
+ this->m_co[0] *= s; this->m_co[1] *= s; this->m_co[2] *= s;
+ return *this;
+ }
+
+ Vector3<Scalar>& operator/=(const Scalar& s)
+ {
+ assert(s != Scalar(0.0));
+ return *this *= Scalar(1.0) / s;
+ }
+
+ Scalar dot(const Vector3<Scalar>& v) const
+ {
+ return this->m_co[0] * v[0] + this->m_co[1] * v[1] + this->m_co[2] * v[2];
+ }
+
+ Scalar length2() const
+ {
+ return dot(*this);
+ }
+
+ Scalar length() const
+ {
+ return Scalar_traits<Scalar>::sqrt(length2());
+ }
+
+ Scalar distance2(const Vector3<Scalar>& v) const
+ {
+ return (v - *this).length2();
+ }
+
+ Scalar distance(const Vector3<Scalar>& v) const
+ {
+ return (v - *this).length();
+ }
+
+ Vector3<Scalar>& normalize()
+ {
+ return *this /= length();
+ }
+
+ Vector3<Scalar> normalized() const
+ {
+ return *this / length();
+ }
+
+ Scalar angle(const Vector3<Scalar>& v) const
+ {
+ Scalar s = Scalar_traits<Scalar>::sqrt(length2() * v.length2());
+ assert(s != Scalar(0.0));
+ return Scalar_traits<Scalar>::acos(dot(v) / s);
+ }
+
+ Vector3<Scalar> absolute() const
+ {
+ return Vector3<Scalar>(Scalar_traits<Scalar>::abs(this->m_co[0]),
+ Scalar_traits<Scalar>::abs(this->m_co[1]),
+ Scalar_traits<Scalar>::abs(this->m_co[2]));
+ }
+
+ Vector3<Scalar> cross(const Vector3<Scalar>& v) const
+ {
+ return Vector3<Scalar>(this->m_co[1] * v[2] - this->m_co[2] * v[1],
+ this->m_co[2] * v[0] - this->m_co[0] * v[2],
+ this->m_co[0] * v[1] - this->m_co[1] * v[0]);
+ }
+
+ Scalar triple(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2) const
+ {
+ return this->m_co[0] * (v1[1] * v2[2] - v1[2] * v2[1]) +
+ this->m_co[1] * (v1[2] * v2[0] - v1[0] * v2[2]) +
+ this->m_co[2] * (v1[0] * v2[1] - v1[1] * v2[0]);
+ }
+
+ int minAxis() const
+ {
+ return this->m_co[0] < this->m_co[1] ? (this->m_co[0] < this->m_co[2] ? 0 : 2) : (this->m_co[1] < this->m_co[2] ? 1 : 2);
+ }
+
+ int maxAxis() const
+ {
+ return this->m_co[0] < this->m_co[1] ? (this->m_co[1] < this->m_co[2] ? 2 : 1) : (this->m_co[0] < this->m_co[2] ? 2 : 0);
+ }
+
+ int furthestAxis() const
+ {
+ return absolute().minAxis();
+ }
+
+ int closestAxis() const
+ {
+ return absolute().maxAxis();
+ }
+
+ Vector3<Scalar> lerp(const Vector3<Scalar>& v, const Scalar& t) const
+ {
+ return Vector3<Scalar>(this->m_co[0] + (v[0] - this->m_co[0]) * t,
+ this->m_co[1] + (v[1] - this->m_co[1]) * t,
+ this->m_co[2] + (v[2] - this->m_co[2]) * t);
+ }
+
+ static Vector3<Scalar> random()
+ {
+ Scalar z = Scalar(2.0) * Scalar_traits<Scalar>::random() - Scalar(1.0);
+ Scalar r = Scalar_traits<Scalar>::sqrt(Scalar(1.0) - z * z);
+ Scalar t = Scalar_traits<Scalar>::TwoTimesPi() * Scalar_traits<Scalar>::random();
+ return Vector3<Scalar>(r * Scalar_traits<Scalar>::cos(t),
+ r * Scalar_traits<Scalar>::sin(t),
+ z);
+ }
+ };
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator+(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return Vector3<Scalar>(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator-(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return Vector3<Scalar>(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator-(const Vector3<Scalar>& v)
+ {
+ return Vector3<Scalar>(-v[0], -v[1], -v[2]);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator*(const Vector3<Scalar>& v, const Scalar& s)
+ {
+ return Vector3<Scalar>(v[0] * s, v[1] * s, v[2] * s);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator*(const Scalar& s, const Vector3<Scalar>& v)
+ {
+ return v * s;
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ operator/(const Vector3<Scalar>& v, const Scalar& s)
+ {
+ assert(s != Scalar(0.0));
+ return v * (Scalar(1.0) / s);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ dot(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return v1.dot(v2);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ length2(const Vector3<Scalar>& v)
+ {
+ return v.length2();
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ length(const Vector3<Scalar>& v)
+ {
+ return v.length();
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ distance2(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return v1.distance2(v2);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ distance(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return v1.distance(v2);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ angle(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return v1.angle(v2);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ cross(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2)
+ {
+ return v1.cross(v2);
+ }
+
+ template <typename Scalar>
+ inline Scalar
+ triple(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2, const Vector3<Scalar>& v3)
+ {
+ return v1.triple(v2, v3);
+ }
+
+ template <typename Scalar>
+ inline Vector3<Scalar>
+ lerp(const Vector3<Scalar>& v1, const Vector3<Scalar>& v2, const Scalar& t)
+ {
+ return v1.lerp(v2, t);
+ }
+
+}
+
+#endif
diff --git a/extern/solid/include/MT_BBox.h b/extern/solid/include/MT_BBox.h
new file mode 100644
index 00000000000..b5dc537e0d9
--- /dev/null
+++ b/extern/solid/include/MT_BBox.h
@@ -0,0 +1,119 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_BBOX_H
+#define MT_BBOX_H
+
+#include "MT_Scalar.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+
+#include <MT/Tuple3.h>
+#include "MT_Interval.h"
+
+
+
+class MT_BBox : public MT::Tuple3<MT_Interval> {
+public:
+ MT_BBox() {}
+ MT_BBox(const MT_Point3& p)
+ : MT::Tuple3<MT_Interval>(MT_Interval(p[0]),
+ MT_Interval(p[1]),
+ MT_Interval(p[2]))
+ {}
+ MT_BBox(const MT_Point3& lb, const MT_Point3& ub)
+ : MT::Tuple3<MT_Interval>(MT_Interval(lb[0], ub[0]),
+ MT_Interval(lb[1], ub[1]),
+ MT_Interval(lb[2], ub[2]))
+ {}
+ MT_BBox(const MT_Interval& x, const MT_Interval& y, const MT_Interval& z)
+ : MT::Tuple3<MT_Interval>(x, y, z)
+ {}
+
+ MT_Point3 getMin() const
+ {
+ return MT_Point3(m_co[0].lower(), m_co[1].lower(), m_co[2].lower());
+ }
+
+ MT_Point3 getMax() const
+ {
+ return MT_Point3(m_co[0].upper(), m_co[1].upper(), m_co[2].upper());
+ }
+
+ MT_Point3 getCenter() const
+ {
+ return MT_Point3(MT::median(m_co[0]), MT::median(m_co[1]), MT::median(m_co[2]));
+ }
+
+ MT_Vector3 getExtent() const
+ {
+ return MT_Vector3(MT::width(m_co[0]) * MT_Scalar(0.5), MT::width(m_co[1]) * MT_Scalar(0.5), MT::width(m_co[2]) * MT_Scalar(0.5));
+ }
+
+ void extend(const MT_Vector3& v)
+ {
+ m_co[0] = MT::widen(m_co[0], v[0]);
+ m_co[1] = MT::widen(m_co[1], v[1]);
+ m_co[2] = MT::widen(m_co[2], v[2]);
+ }
+
+ bool overlaps(const MT_BBox& b) const
+ {
+ return MT::overlap(m_co[0], b[0]) &&
+ MT::overlap(m_co[1], b[1]) &&
+ MT::overlap(m_co[2], b[2]);
+ }
+
+ bool inside(const MT_BBox& b) const
+ {
+ return MT::in(m_co[0], b[0]) &&
+ MT::in(m_co[1], b[1]) &&
+ MT::in(m_co[2], b[2]);
+ }
+
+ MT_BBox hull(const MT_BBox& b) const
+ {
+ return MT_BBox(MT::hull(m_co[0], b[0]),
+ MT::hull(m_co[1], b[1]),
+ MT::hull(m_co[2], b[2]));
+ }
+
+ bool contains(const MT_Point3& p) const
+ {
+ return MT::in(p[0], m_co[0]) && MT::in(p[1], m_co[1]) && MT::in(p[2], m_co[2]);
+ }
+};
+
+inline MT_BBox operator+(const MT_BBox& b1, const MT_BBox& b2)
+{
+ return MT_BBox(b1[0] + b2[0], b1[1] + b2[1], b1[2] + b2[2]);
+}
+
+inline MT_BBox operator-(const MT_BBox& b1, const MT_BBox& b2)
+{
+ return MT_BBox(b1[0] - b2[0], b1[1] - b2[1], b1[2] - b2[2]);
+}
+
+#endif
+
+
diff --git a/extern/solid/include/MT_Interval.h b/extern/solid/include/MT_Interval.h
new file mode 100644
index 00000000000..25ebfd0a67d
--- /dev/null
+++ b/extern/solid/include/MT_Interval.h
@@ -0,0 +1,33 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_INTERVAL_H
+#define MT_INTERVAL_H
+
+#include <MT/Interval.h>
+
+#include "MT_Scalar.h"
+
+typedef MT::Interval<MT_Scalar> MT_Interval;
+
+#endif
diff --git a/extern/solid/include/MT_Matrix3x3.h b/extern/solid/include/MT_Matrix3x3.h
new file mode 100644
index 00000000000..f7572f90fa2
--- /dev/null
+++ b/extern/solid/include/MT_Matrix3x3.h
@@ -0,0 +1,34 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_MATRIX3X3_H
+#define MT_MATRIX3X3_H
+
+#include "MT_Scalar.h"
+#include <MT/Matrix3x3.h>
+
+typedef MT::Matrix3x3<MT_Scalar> MT_Matrix3x3;
+
+
+
+#endif
diff --git a/extern/solid/include/MT_Point3.h b/extern/solid/include/MT_Point3.h
new file mode 100644
index 00000000000..ca84f652b65
--- /dev/null
+++ b/extern/solid/include/MT_Point3.h
@@ -0,0 +1,31 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_POINT3_H
+#define MT_POINT3_H
+
+#include "MT_Vector3.h"
+
+typedef MT_Vector3 MT_Point3;
+
+#endif
diff --git a/extern/solid/include/MT_Quaternion.h b/extern/solid/include/MT_Quaternion.h
new file mode 100644
index 00000000000..ca860db711c
--- /dev/null
+++ b/extern/solid/include/MT_Quaternion.h
@@ -0,0 +1,35 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_QUATERNION_H
+#define MT_QUATERNION_H
+
+#include "MT_Scalar.h"
+#include <MT/Quaternion.h>
+
+typedef MT::Quaternion<MT_Scalar> MT_Quaternion;
+
+#endif
+
+
+
diff --git a/extern/solid/include/MT_Scalar.h b/extern/solid/include/MT_Scalar.h
new file mode 100644
index 00000000000..663a1f1839c
--- /dev/null
+++ b/extern/solid/include/MT_Scalar.h
@@ -0,0 +1,158 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_SCALAR_H
+#define MT_SCALAR_H
+
+#if defined (__sun__) || defined ( __sun ) || defined (__sparc) || defined (__sparc__) || defined (__sgi)
+#include <math.h>
+#include <float.h>
+#else
+#include <cmath>
+#include <cstdlib>
+#include <cfloat>
+#endif
+
+#undef max
+
+#include "SOLID_types.h"
+
+#include "GEN_MinMax.h"
+#include "GEN_random.h"
+
+template <typename Scalar>
+struct Scalar_traits {};
+
+template<>
+struct Scalar_traits<float> {
+ static float TwoTimesPi() { return 6.283185307179586232f; }
+ static float epsilon() { return FLT_EPSILON; }
+ static float max() { return FLT_MAX; }
+
+ static float random() { return float(GEN_rand()) / float(GEN_RAND_MAX); }
+#if defined (__sun) || defined (__sun__) || defined (__sparc) || defined (__APPLE__)
+ static float sqrt(float x) { return ::sqrt(x); }
+ static float abs(float x) { return ::fabs(x); }
+
+ static float cos(float x) { return ::cos(x); }
+ static float sin(float x) { return ::sin(x); }
+ static float tan(float x) { return ::tan(x); }
+
+ static float acos(float x) { return ::acos(x); }
+ static float asin(float x) { return ::asin(x); }
+ static float atan(float x) { return ::atan(x); }
+ static float atan2(float x, float y) { return ::atan2(x, y); }
+
+ static float exp(float x) { return ::exp(x); }
+ static float log(float x) { return ::log(x); }
+ static float pow(float x, float y) { return ::pow(x, y); }
+
+#else
+ static float sqrt(float x) { return ::sqrtf(x); }
+ static float abs(float x) { return ::fabsf(x); }
+
+ static float cos(float x) { return ::cosf(x); }
+ static float sin(float x) { return ::sinf(x); }
+ static float tan(float x) { return ::tanf(x); }
+
+ static float acos(float x) { return ::acosf(x); }
+ static float asin(float x) { return ::asinf(x); }
+ static float atan(float x) { return ::atanf(x); }
+ static float atan2(float x, float y) { return ::atan2f(x, y); }
+
+ static float exp(float x) { return ::expf(x); }
+ static float log(float x) { return ::logf(x); }
+ static float pow(float x, float y) { return ::powf(x, y); }
+#endif
+};
+
+template<>
+struct Scalar_traits<double> {
+ static double TwoTimesPi() { return 6.283185307179586232; }
+ static double epsilon() { return DBL_EPSILON; }
+ static double max() { return DBL_MAX; }
+
+ static double random() { return double(GEN_rand()) / double(GEN_RAND_MAX); }
+ static double sqrt(double x) { return ::sqrt(x); }
+ static double abs(double x) { return ::fabs(x); }
+
+ static double cos(double x) { return ::cos(x); }
+ static double sin(double x) { return ::sin(x); }
+ static double tan(double x) { return ::tan(x); }
+
+ static double acos(double x) { return ::acos(x); }
+ static double asin(double x) { return ::asin(x); }
+ static double atan(double x) { return ::atan(x); }
+ static double atan2(double x, double y) { return ::atan2(x, y); }
+
+ static double exp(double x) { return ::exp(x); }
+ static double log(double x) { return ::log(x); }
+ static double pow(double x, double y) { return ::pow(x, y); }
+};
+
+#ifdef USE_TRACER
+#include "MT_ScalarTracer.h"
+
+#ifdef USE_DOUBLES
+typedef MT_ScalarTracer<double> MT_Scalar;
+#else
+typedef MT_ScalarTracer<float> MT_Scalar;
+#endif
+
+#else
+
+#ifdef USE_DOUBLES
+typedef double MT_Scalar;
+#else
+typedef float MT_Scalar;
+#endif
+
+#endif
+
+
+const MT_Scalar MT_2_PI = Scalar_traits<MT_Scalar>::TwoTimesPi();
+const MT_Scalar MT_PI = MT_2_PI * MT_Scalar(0.5);
+const MT_Scalar MT_HALF_PI = MT_2_PI * MT_Scalar(0.25);
+const MT_Scalar MT_RADS_PER_DEG = MT_2_PI / MT_Scalar(360.0);
+const MT_Scalar MT_DEGS_PER_RAD = MT_Scalar(360.0) / MT_2_PI;
+
+const MT_Scalar MT_EPSILON = Scalar_traits<MT_Scalar>::epsilon();
+const MT_Scalar MT_INFINITY = Scalar_traits<MT_Scalar>::max();
+
+inline MT_Scalar MT_random() { return Scalar_traits<MT_Scalar>::random(); }
+inline MT_Scalar MT_abs(MT_Scalar x) { return Scalar_traits<MT_Scalar>::abs(x); }
+inline MT_Scalar MT_sqrt(MT_Scalar x) { return Scalar_traits<MT_Scalar>::sqrt(x); }
+
+inline MT_Scalar MT_cos(MT_Scalar x) { return Scalar_traits<MT_Scalar>::cos(x); }
+inline MT_Scalar MT_sin(MT_Scalar x) { return Scalar_traits<MT_Scalar>::sin(x); }
+inline MT_Scalar MT_tan(MT_Scalar x) { return Scalar_traits<MT_Scalar>::tan(x); }
+
+inline MT_Scalar MT_acos(MT_Scalar x) { return Scalar_traits<MT_Scalar>::acos(x); }
+inline MT_Scalar MT_asin(MT_Scalar x) { return Scalar_traits<MT_Scalar>::asin(x); }
+inline MT_Scalar MT_atan(MT_Scalar x) { return Scalar_traits<MT_Scalar>::atan(x); }
+inline MT_Scalar MT_atan2(MT_Scalar x, MT_Scalar y) { return Scalar_traits<MT_Scalar>::atan2(x, y); }
+
+inline MT_Scalar MT_radians(MT_Scalar x) { return x * MT_RADS_PER_DEG; }
+inline MT_Scalar MT_degrees(MT_Scalar x) { return x * MT_DEGS_PER_RAD; }
+
+#endif
diff --git a/extern/solid/include/MT_Transform.h b/extern/solid/include/MT_Transform.h
new file mode 100644
index 00000000000..66f92428054
--- /dev/null
+++ b/extern/solid/include/MT_Transform.h
@@ -0,0 +1,38 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_TRANSFORM_H
+#define MT_TRANSFORM_H
+
+#include "MT_Scalar.h"
+#include <MT/Transform.h>
+
+typedef MT::Matrix3x3<MT_Scalar> MT_Matrix3x3;
+typedef MT::Transform<MT_Scalar> MT_Transform;
+
+#endif
+
+
+
+
+
diff --git a/extern/solid/include/MT_Vector3.h b/extern/solid/include/MT_Vector3.h
new file mode 100644
index 00000000000..d50e80dc287
--- /dev/null
+++ b/extern/solid/include/MT_Vector3.h
@@ -0,0 +1,50 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef MT_VECTOR3_H
+#define MT_VECTOR3_H
+
+#include "MT_Scalar.h"
+#include <MT/Vector3.h>
+
+typedef MT::Vector3<MT_Scalar> MT_Vector3;
+
+#ifdef CPU_CMP
+
+inline bool operator==(const MT_Vector3& p1, const MT_Vector3& p2)
+{
+ const unsigned int *i1 = (const unsigned int *)&p1;
+ const unsigned int *i2 = (const unsigned int *)&p2;
+ return i1[0] == i2[0] && i1[1] == i2[1] && i1[2] == i2[2];
+}
+
+#else
+
+inline bool operator==(const MT_Vector3& p1, const MT_Vector3& p2)
+{
+ return p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2];
+}
+
+#endif
+
+#endif
diff --git a/extern/solid/include/SOLID.h b/extern/solid/include/SOLID.h
new file mode 100644
index 00000000000..96d40f1ea6b
--- /dev/null
+++ b/extern/solid/include/SOLID.h
@@ -0,0 +1,279 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_H
+#define SOLID_H
+
+#include "SOLID_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ DT_DECLARE_HANDLE(DT_ObjectHandle);
+ DT_DECLARE_HANDLE(DT_SceneHandle);
+ DT_DECLARE_HANDLE(DT_ShapeHandle);
+ DT_DECLARE_HANDLE(DT_VertexBaseHandle);
+ DT_DECLARE_HANDLE(DT_RespTableHandle);
+ DT_DECLARE_HANDLE(DT_ArchiveHandle);
+
+ typedef unsigned int DT_ResponseClass;
+
+ typedef enum DT_ResponseType {
+ DT_NO_RESPONSE, /* No response (obsolete) */
+ DT_BROAD_RESPONSE, /* Broad phase response is returned. */
+ DT_SIMPLE_RESPONSE, /* No collision data */
+ DT_WITNESSED_RESPONSE, /* A point common to both objects
+ is returned as collision data
+ */
+ DT_DEPTH_RESPONSE /* The penetration depth is returned
+ as collision data. The penetration depth
+ is the shortest vector over which one
+ object needs to be translated in order
+ to bring the objects in touching contact.
+ */
+ } DT_ResponseType;
+
+/* For witnessed response, the following structure represents a common point. The world
+ coordinates of 'point1' and 'point2' coincide. 'normal' is the zero vector.
+
+ For depth response, the following structure represents the penetration depth.
+ 'point1' en 'point2' are the witness points of the penetration depth in world coordinates.
+ The penetration depth vector in world coordinates is represented by 'normal'.
+*/
+
+ typedef struct DT_CollData {
+ DT_Vector3 point1; /* Point in object1 in world coordinates */
+ DT_Vector3 point2; /* Point in object2 in world coordinates */
+ DT_Vector3 normal; /* point2 - point1 */
+ } DT_CollData;
+
+/* A response callback is called by SOLID for each pair of collding objects. 'client-data'
+ is a pointer to an arbitrary structure in the client application. The client objects are
+ pointers to structures in the client application associated with the coliding objects.
+ 'coll_data' is the collision data computed by SOLID.
+*/
+
+ typedef DT_Bool (*DT_ResponseCallback)(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+/* Shape definition */
+
+
+ extern DECLSPEC DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+ extern DECLSPEC DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height);
+ extern DECLSPEC DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height);
+ extern DECLSPEC DT_ShapeHandle DT_NewSphere(DT_Scalar radius);
+ extern DECLSPEC DT_ShapeHandle DT_NewPoint(const DT_Vector3 point);
+ extern DECLSPEC DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target);
+ extern DECLSPEC DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
+ extern DECLSPEC DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
+
+ extern DECLSPEC DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride);
+ extern DECLSPEC void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer);
+
+ extern DECLSPEC DT_ShapeHandle DT_NewComplexShape(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_EndComplexShape();
+
+ extern DECLSPEC DT_ShapeHandle DT_NewPolytope(DT_VertexBaseHandle vertexBase);
+ extern DECLSPEC void DT_EndPolytope();
+
+ extern DECLSPEC void DT_Begin();
+ extern DECLSPEC void DT_End();
+
+ extern DECLSPEC void DT_Vertex(const DT_Vector3 vertex);
+ extern DECLSPEC void DT_VertexIndex(DT_Index index);
+
+ extern DECLSPEC void DT_VertexIndices(DT_Count count, const DT_Index *indices);
+ extern DECLSPEC void DT_VertexRange(DT_Index first, DT_Count count);
+
+ extern DECLSPEC void DT_DeleteShape(DT_ShapeHandle shape);
+
+/* Object */
+
+ extern DECLSPEC DT_ObjectHandle DT_CreateObject(
+ void *client_object, /* pointer to object in client memory */
+ DT_ShapeHandle shape /* the shape or geometry of the object */
+ );
+
+ extern DECLSPEC void DT_DestroyObject(DT_ObjectHandle object);
+
+
+
+ extern DECLSPEC void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
+ extern DECLSPEC void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
+ extern DECLSPEC void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
+
+/* The margin is an offset from the actual shape. The actual geometry of an
+ object is the set of points whose distance to the transformed shape is at
+ most the margin. During the lifetime of an object the margin can be
+ modified.
+*/
+
+ extern DECLSPEC void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
+
+
+/* These commands assume a column-major 4x4 OpenGL matrix representation */
+
+ extern DECLSPEC void DT_SetMatrixf(DT_ObjectHandle object, const float *m);
+ extern DECLSPEC void DT_GetMatrixf(DT_ObjectHandle object, float *m);
+
+ extern DECLSPEC void DT_SetMatrixd(DT_ObjectHandle object, const double *m);
+ extern DECLSPEC void DT_GetMatrixd(DT_ObjectHandle object, double *m);
+
+ extern DECLSPEC void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max);
+
+
+ extern DECLSPEC DT_Bool DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 v);
+/* This next command returns the distance between the objects. De returned
+ closest points are given in world coordinates.
+*/
+ extern DECLSPEC DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+ extern DECLSPEC DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point);
+
+ extern DECLSPEC DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+/* Scene */
+
+ extern DECLSPEC DT_SceneHandle DT_CreateScene();
+ extern DECLSPEC void DT_DestroyScene(DT_SceneHandle scene);
+
+ extern DECLSPEC void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
+ extern DECLSPEC void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
+
+/* Note that objects can be assigned to multiple scenes! */
+
+/* Response */
+
+/* Response tables are defined independent of the scenes in which they are used.
+ Multiple response tables can be used in one scene, and a response table
+ can be shared among scenes.
+*/
+ extern DECLSPEC DT_RespTableHandle DT_CreateRespTable();
+ extern DECLSPEC void DT_DestroyRespTable(DT_RespTableHandle respTable);
+
+/* Responses are defined on (pairs of) response classes. Each response table
+ maintains its set of response classes.
+*/
+ extern DECLSPEC DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable);
+
+/* To each object for which a response is defined in the response table a
+ response class needs to be assigned.
+*/
+
+ extern DECLSPEC void DT_SetResponseClass(DT_RespTableHandle respTable,
+ DT_ObjectHandle object,
+ DT_ResponseClass responseClass);
+
+ extern DECLSPEC void DT_ClearResponseClass(DT_RespTableHandle respTable,
+ DT_ObjectHandle object);
+
+ extern DECLSPEC void DT_CallResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ const DT_CollData *coll_data);
+
+/* For each pair of objects multiple responses can be defined. A response is a callback
+ together with its response type and client data. */
+
+/* Responses can be defined for all pairs of response classes... */
+ extern DECLSPEC void DT_AddDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+
+ extern DECLSPEC void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response);
+/* ...per response class... */
+ extern DECLSPEC void DT_AddClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+
+ extern DECLSPEC void DT_RemoveClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response);
+
+/* ... and per pair of response classes...*/
+ extern DECLSPEC void DT_AddPairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+ extern DECLSPEC void DT_RemovePairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response);
+
+/* The next command calls the response callbacks for all intersecting pairs of objects in a scene.
+ 'DT_Test' returns the number of pairs of objects for which callbacks have been called.
+*/
+
+ extern DECLSPEC DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
+
+/* Set the maximum relative error in the closest points and penetration depth
+ computation. The default for `max_error' is 1.0e-3. Larger errors result
+ in better performance. Non-positive error tolerances are ignored.
+*/
+
+ extern DECLSPEC void DT_SetAccuracy(DT_Scalar max_error);
+
+/* Set the maximum tolerance on relative errors due to rounding. The default for `tol_error'
+ is the machine epsilon. Very large tolerances result in false collisions. Setting tol_error too small
+ results in missed collisions. Non-positive error tolerances are ignored.
+*/
+
+ extern DECLSPEC void DT_SetTolerance(DT_Scalar tol_error);
+
+
+/* This function returns the client pointer to the first object in a scene hit by the ray
+ (actually a line segment) defined by the points 'from' en 'to'. The spot is the hit point
+ on the object in local coordinates. 'normal' is the normal to the surface of the object in
+ world coordinates. The ignore_client pointer is used to make one of the objects transparent.
+
+ NB: Currently ray tests are implemented for spheres, boxes, and meshes only!!
+*/
+
+ extern DECLSPEC void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
+
+/* Similar, only here a single object is tested and a boolean is returned */
+
+ extern DECLSPEC DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/solid/include/SOLID_broad.h b/extern/solid/include/SOLID_broad.h
new file mode 100644
index 00000000000..74e4214fa67
--- /dev/null
+++ b/extern/solid/include/SOLID_broad.h
@@ -0,0 +1,75 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_BROAD_H
+#define SOLID_BROAD_H
+
+#include "SOLID_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ DT_DECLARE_HANDLE(BP_SceneHandle);
+ DT_DECLARE_HANDLE(BP_ProxyHandle);
+
+ typedef void (*BP_Callback)(void *client_data,
+ void *object1,
+ void *object2);
+
+ typedef bool (*BP_RayCastCallback)(void *client_data,
+ void *object,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda);
+
+ extern DECLSPEC BP_SceneHandle BP_CreateScene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap);
+
+ extern DECLSPEC void BP_DestroyScene(BP_SceneHandle scene);
+
+ extern DECLSPEC BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene,
+ void *object,
+ const DT_Vector3 min,
+ const DT_Vector3 max);
+
+ extern DECLSPEC void BP_DestroyProxy(BP_SceneHandle scene,
+ BP_ProxyHandle proxy);
+
+ extern DECLSPEC void BP_SetBBox(BP_ProxyHandle proxy,
+ const DT_Vector3 min,
+ const DT_Vector3 max);
+
+ extern DECLSPEC void *BP_RayCast(BP_SceneHandle scene,
+ BP_RayCastCallback objectRayCast,
+ void *client_data,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/solid/include/SOLID_types.h b/extern/solid/include/SOLID_types.h
new file mode 100644
index 00000000000..630594e447f
--- /dev/null
+++ b/extern/solid/include/SOLID_types.h
@@ -0,0 +1,53 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef SOLID_TYPES_H
+#define SOLID_TYPES_H
+
+#ifndef DECLSPEC
+# ifdef WIN32
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+#endif
+
+#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+
+typedef unsigned short DT_Index;
+typedef unsigned short DT_Count;
+typedef unsigned int DT_Size;
+typedef float DT_Scalar;
+typedef int DT_Bool;
+
+#define DT_FALSE 0
+#define DT_TRUE 1
+
+#define DT_CONTINUE 0
+#define DT_DONE 1
+
+typedef DT_Scalar DT_Vector3[3];
+typedef DT_Scalar DT_Quaternion[4];
+
+#endif
diff --git a/extern/solid/make/msvc_7_0/broad/broad.vcproj b/extern/solid/make/msvc_7_0/broad/broad.vcproj
new file mode 100644
index 00000000000..adb56424e60
--- /dev/null
+++ b/extern/solid/make/msvc_7_0/broad/broad.vcproj
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="broad"
+ ProjectGUID="{0112CAD5-3584-412A-A2E5-1315A00437B4}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\broad.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\debug\broad.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\broad.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\broad\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\debug\broad.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\..\src\broad\BP_C-api.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_EndpointList.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_Proxy.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_Scene.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\src\broad\BP_Endpoint.h">
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_EndpointList.h">
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_Proxy.h">
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_ProxyList.h">
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_Scene.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_7_0/complex/complex.vcproj b/extern/solid/make/msvc_7_0/complex/complex.vcproj
new file mode 100644
index 00000000000..2a895fa28d3
--- /dev/null
+++ b/extern/solid/make/msvc_7_0/complex/complex.vcproj
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="complex"
+ ProjectGUID="{B83C6BED-11EC-46C8-AFFA-121EEDE94373}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\complex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\complex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug\complex.pch"
+ AssemblerOutput="0"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\debug\complex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\complex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\complex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug\complex.pch"
+ AssemblerOutput="0"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\complex\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\debug\complex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\..\src\complex\DT_BBoxTree.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\complex\DT_Complex.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\src\complex\DT_BBoxTree.h">
+ </File>
+ <File
+ RelativePath="..\..\src\complex\DT_CBox.h">
+ </File>
+ <File
+ RelativePath="..\..\src\complex\DT_Complex.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_7_0/convex/convex.vcproj b/extern/solid/make/msvc_7_0/convex/convex.vcproj
new file mode 100644
index 00000000000..da088b5972f
--- /dev/null
+++ b/extern/solid/make/msvc_7_0/convex/convex.vcproj
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="convex"
+ ProjectGUID="{524264F4-DF21-4B79-847F-E7CA643ECD0B}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\debug\convex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\convex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\convex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\extern\solid\convex\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\extern\mtdll\debug\convex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\..\src\convex\DT_Accuracy.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Box.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Cone.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Convex.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Cylinder.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Facet.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_LineSegment.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_PenDepth.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Point.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Polyhedron.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Polytope.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Sphere.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Triangle.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\src\convex\DT_Accuracy.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Array.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Box.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Cone.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Convex.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Cylinder.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Facet.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_GJK.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Hull.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_IndexArray.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_LineSegment.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Minkowski.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_PenDepth.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Point.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Polyhedron.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Polytope.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Shape.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Sphere.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Transform.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Triangle.h">
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_VertexBase.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_7_0/solid.vcproj b/extern/solid/make/msvc_7_0/solid.vcproj
new file mode 100644
index 00000000000..d9e6332987c
--- /dev/null
+++ b/extern/solid/make/msvc_7_0/solid.vcproj
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="solid"
+ ProjectGUID="{D696C86B-0B53-4471-A50D-5B983A6FA4AD}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\solid\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\solid\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\solid\debug\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\solid\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\solid\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\solid\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\debug\solid.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\solid"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\solid"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\solid\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\solid\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\solid\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\solid\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\solid.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\solid\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\solid\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\mtdll\solid.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\extern\solid\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\extern\mtdll\debug\solid.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_7\extern\solid\include\SOLID
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\src\DT_C-api.cpp">
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Encounter.cpp">
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Object.cpp">
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_RespTable.cpp">
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Scene.cpp">
+ <FileConfiguration
+ Name="Blender Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\src\DT_AlgoTable.h">
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Encounter.h">
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Object.h">
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Response.h">
+ </File>
+ <File
+ RelativePath="..\..\src\DT_RespTable.h">
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Scene.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_9_0/broad/broad.vcproj b/extern/solid/make/msvc_9_0/broad/broad.vcproj
new file mode 100644
index 00000000000..c58cb08b2c3
--- /dev/null
+++ b/extern/solid/make/msvc_9_0/broad/broad.vcproj
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="EXT_broad"
+ ProjectGUID="{0112CAD5-3584-412A-A2E5-1315A00437B4}"
+ RootNamespace="broad"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\broad.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\debug\broad.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\broad.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug\broad.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\broad\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\debug\broad.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\..\src\broad\BP_C-api.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_EndpointList.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_Proxy.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\broad\BP_Scene.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\src\broad\BP_Endpoint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_EndpointList.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_Proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_ProxyList.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\broad\BP_Scene.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_9_0/complex/complex.vcproj b/extern/solid/make/msvc_9_0/complex/complex.vcproj
new file mode 100644
index 00000000000..1828c489fc6
--- /dev/null
+++ b/extern/solid/make/msvc_9_0/complex/complex.vcproj
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="EXT_complex"
+ ProjectGUID="{B83C6BED-11EC-46C8-AFFA-121EEDE94373}"
+ RootNamespace="complex"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\complex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\complex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug\complex.pch"
+ AssemblerOutput="0"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\debug\complex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\complex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\complex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\src\convex"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug\complex.pch"
+ AssemblerOutput="0"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\complex\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\debug\complex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\..\src\complex\DT_BBoxTree.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\complex\DT_Complex.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\src\complex\DT_BBoxTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\complex\DT_CBox.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\complex\DT_Complex.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_9_0/convex/convex.vcproj b/extern/solid/make/msvc_9_0/convex/convex.vcproj
new file mode 100644
index 00000000000..cb35a0ea199
--- /dev/null
+++ b/extern/solid/make/msvc_9_0/convex/convex.vcproj
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="EXT_convex"
+ ProjectGUID="{524264F4-DF21-4B79-847F-E7CA643ECD0B}"
+ RootNamespace="convex"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\debug\convex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\convex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\convex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\qhull\include"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug\convex.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\extern\solid\convex\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\extern\mtdll\debug\convex.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\..\src\convex\DT_Accuracy.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Box.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Cone.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Convex.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Cylinder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Facet.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_LineSegment.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_PenDepth.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Point.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Polyhedron.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Polytope.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Sphere.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\convex\DT_Triangle.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\src\convex\DT_Accuracy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Array.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Box.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Cone.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Convex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Cylinder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Facet.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_GJK.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Hull.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_IndexArray.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_LineSegment.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Minkowski.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_PenDepth.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Point.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Polyhedron.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Polytope.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Shape.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Sphere.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Transform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_Triangle.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\convex\DT_VertexBase.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/make/msvc_9_0/solid.vcproj b/extern/solid/make/msvc_9_0/solid.vcproj
new file mode 100644
index 00000000000..ed81c374696
--- /dev/null
+++ b/extern/solid/make/msvc_9_0/solid.vcproj
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="EXT_solid"
+ ProjectGUID="{D696C86B-0B53-4471-A50D-5B983A6FA4AD}"
+ RootNamespace="solid"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\solid\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\solid\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\solid\debug\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\solid\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\solid\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\solid\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\debug\solid.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\solid"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\solid"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\solid\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\solid\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\solid\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\solid\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\solid.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\solid\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\solid\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="NDEBUG;QHULL;WIN32;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\mtdll\solid.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3D Plugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include;..\..\src\convex;..\..\src\complex"
+ PreprocessorDefinitions="_DEBUG;QHULL;WIN32;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug\solid.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\extern\solid\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\extern\mtdll\debug\solid.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SOLID files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID MKDIR ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;XCOPY /Y ..\..\include\SOLID*.h ..\..\..\..\..\build\msvc_9\extern\solid\include\SOLID&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\src\DT_C-api.cpp"
+ >
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Encounter.cpp"
+ >
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Object.cpp"
+ >
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_RespTable.cpp"
+ >
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Scene.cpp"
+ >
+ <FileConfiguration
+ Name="Blender Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Blender Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="3D Plugin Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\src\DT_AlgoTable.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Encounter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Object.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Response.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\DT_RespTable.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\DT_Scene.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extern/solid/src/DT_AlgoTable.h b/extern/solid/src/DT_AlgoTable.h
new file mode 100644
index 00000000000..0749ca7fdd9
--- /dev/null
+++ b/extern/solid/src/DT_AlgoTable.h
@@ -0,0 +1,47 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_ALGOTABLE_H
+#define DT_ALGOTABLE_H
+
+#include "DT_Shape.h"
+
+template <typename Function, int NUM_TYPES = 8>
+class AlgoTable {
+public:
+ void addEntry(DT_ShapeType type1, DT_ShapeType type2, Function function)
+ {
+ table[type2][type1] = function;
+ table[type1][type2] = function;
+ }
+
+ Function lookup(DT_ShapeType type1, DT_ShapeType type2) const
+ {
+ return table[type1][type2];
+ }
+
+private:
+ Function table[NUM_TYPES][NUM_TYPES];
+};
+
+#endif
diff --git a/extern/solid/src/DT_C-api.cpp b/extern/solid/src/DT_C-api.cpp
new file mode 100644
index 00000000000..ac16deda87d
--- /dev/null
+++ b/extern/solid/src/DT_C-api.cpp
@@ -0,0 +1,581 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+
+#include "SOLID.h"
+
+#include "DT_Box.h"
+#include "DT_Cone.h"
+#include "DT_Cylinder.h"
+#include "DT_Sphere.h"
+#include "DT_Complex.h"
+#include "DT_Polytope.h"
+#include "DT_Polyhedron.h"
+#include "DT_Point.h"
+#include "DT_LineSegment.h"
+#include "DT_Triangle.h"
+#include "DT_Minkowski.h"
+#include "DT_Hull.h"
+
+#include "DT_Response.h"
+#include "DT_RespTable.h"
+
+#include "DT_Scene.h"
+#include "DT_Object.h"
+
+#include "DT_VertexBase.h"
+
+#include "DT_Accuracy.h"
+
+typedef MT::Tuple3<DT_Scalar> T_Vertex;
+typedef std::vector<T_Vertex> T_VertexBuf;
+typedef std::vector<DT_Index> T_IndexBuf;
+typedef std::vector<const DT_Convex *> T_PolyList;
+
+static T_VertexBuf vertexBuf;
+static T_IndexBuf indexBuf;
+static T_PolyList polyList;
+
+static DT_Complex *currentComplex = 0;
+static DT_Polyhedron *currentPolyhedron = 0;
+static DT_VertexBase *currentBase = 0;
+
+
+
+
+
+
+DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride)
+{
+ return (DT_VertexBaseHandle)new DT_VertexBase(pointer, stride);
+}
+
+void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase)
+{
+ delete (DT_VertexBase *)vertexBase;
+}
+
+void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer)
+{
+ DT_VertexBase *base = (DT_VertexBase *)vertexBase;
+ base->setPointer(pointer);
+ const DT_ComplexList& complexList = base->getComplexList();
+ DT_ComplexList::const_iterator it;
+ for (it = complexList.begin(); it != complexList.end(); ++it)
+ {
+ (*it)->refit();
+ }
+}
+
+
+DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z)
+{
+ return (DT_ShapeHandle)new DT_Box(MT_Scalar(x) * MT_Scalar(0.5),
+ MT_Scalar(y) * MT_Scalar(0.5),
+ MT_Scalar(z) * MT_Scalar(0.5));
+}
+
+DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height)
+{
+ return (DT_ShapeHandle)new DT_Cone(MT_Scalar(radius), MT_Scalar(height));
+}
+
+DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height)
+{
+ return (DT_ShapeHandle)new DT_Cylinder(MT_Scalar(radius), MT_Scalar(height));
+}
+
+DT_ShapeHandle DT_NewSphere(DT_Scalar radius)
+{
+ return (DT_ShapeHandle)new DT_Sphere(MT_Scalar(radius));
+}
+
+DT_ShapeHandle DT_NewPoint(const DT_Vector3 point)
+{
+ return (DT_ShapeHandle)new DT_Point(MT_Point3(point));
+}
+
+DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target)
+{
+ return (DT_ShapeHandle)new DT_LineSegment(MT_Point3(source), MT_Point3(target));
+}
+
+DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2)
+{
+ if (((DT_Shape *)shape1)->getType() != CONVEX ||
+ ((DT_Shape *)shape2)->getType() != CONVEX)
+ {
+ return 0;
+ }
+
+ return (DT_ShapeHandle)new DT_Minkowski(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
+}
+
+DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2)
+{
+ if (((DT_Shape *)shape1)->getType() != CONVEX ||
+ ((DT_Shape *)shape2)->getType() != CONVEX)
+ {
+ return 0;
+ }
+
+ return (DT_ShapeHandle)new DT_Hull(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
+}
+
+DT_ShapeHandle DT_NewComplexShape(const DT_VertexBaseHandle vertexBase)
+{
+ if (!currentComplex)
+ {
+ currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
+ currentComplex = new DT_Complex(currentBase);
+ }
+ return (DT_ShapeHandle)currentComplex;
+}
+
+void DT_EndComplexShape()
+{
+ if (currentComplex)
+ {
+ if (currentBase->getPointer() == 0)
+ {
+ T_Vertex *vertexArray = new T_Vertex[vertexBuf.size()];
+ assert(vertexArray);
+ std::copy(vertexBuf.begin(), vertexBuf.end(), &vertexArray[0]);
+ currentBase->setPointer(vertexArray, true);
+ }
+
+ vertexBuf.clear();
+
+ currentComplex->finish(polyList.size(), &polyList[0]);
+ polyList.clear();
+ currentComplex = 0;
+ currentBase = 0;
+ }
+}
+
+DT_ShapeHandle DT_NewPolytope(const DT_VertexBaseHandle vertexBase)
+{
+ if (!currentPolyhedron)
+ {
+ currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
+ currentPolyhedron = new DT_Polyhedron;
+
+ }
+ return (DT_ShapeHandle)currentPolyhedron;
+}
+
+void DT_EndPolytope()
+{
+ if (currentPolyhedron)
+ {
+ if (currentBase->getPointer() == 0)
+ {
+ currentBase->setPointer(&vertexBuf[0]);
+ new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
+
+ delete currentBase;
+ }
+ else
+ {
+ new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
+ }
+ vertexBuf.clear();
+ indexBuf.clear();
+ currentPolyhedron = 0;
+ currentBase = 0;
+ }
+}
+
+void DT_Begin()
+{}
+
+void DT_End()
+{
+ if (currentComplex)
+ {
+ DT_VertexIndices(indexBuf.size(), &indexBuf[0]);
+ indexBuf.clear();
+ }
+}
+
+void DT_Vertex(const DT_Vector3 vertex)
+{
+ MT::Vector3<DT_Scalar> p(vertex);
+ int i = GEN_max((int)vertexBuf.size() - 20, 0);
+ int n = static_cast<int>(vertexBuf.size());
+
+ while (i != n && !(vertexBuf[i] == p))
+ {
+ ++i;
+ }
+
+ if (i == n)
+ {
+ vertexBuf.push_back(p);
+ }
+ indexBuf.push_back(i);
+}
+
+
+void DT_VertexIndex(DT_Index index) { indexBuf.push_back(index); }
+
+void DT_VertexIndices(DT_Count count, const DT_Index *indices)
+{
+ if (currentComplex)
+ {
+ DT_Convex *poly = count == 3 ?
+ static_cast<DT_Convex *>(new DT_Triangle(currentBase, indices[0], indices[1], indices[2])) :
+ static_cast<DT_Convex *>(new DT_Polytope(currentBase, count, indices));
+ polyList.push_back(poly);
+
+ }
+
+ if (currentPolyhedron)
+ {
+ int i;
+ for (i = 0; i < count; ++i)
+ {
+ indexBuf.push_back(indices[i]);
+ }
+ }
+}
+
+void DT_VertexRange(DT_Index first, DT_Count count)
+{
+ DT_Index *indices = new DT_Index[count];
+
+ DT_Index i;
+ for (i = 0; i != count; ++i)
+ {
+ indices[i] = first + i;
+ }
+ DT_VertexIndices(count, indices);
+
+ delete [] indices;
+}
+
+void DT_DeleteShape(DT_ShapeHandle shape)
+{
+ delete (DT_Shape *)shape;
+}
+
+
+
+
+// Scene
+
+
+DT_SceneHandle DT_CreateScene()
+{
+ return (DT_SceneHandle)new DT_Scene;
+}
+
+void DT_DestroyScene(DT_SceneHandle scene)
+{
+ delete (DT_Scene *)scene;
+}
+
+void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((DT_Scene *)scene)->addObject(*(DT_Object *)object);
+}
+
+void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((DT_Scene *)scene)->removeObject(*(DT_Object *)object);
+}
+
+
+// Object instantiation
+
+
+DT_ObjectHandle DT_CreateObject(void *client_object,
+ DT_ShapeHandle shape)
+{
+ return (DT_ObjectHandle)new DT_Object(client_object, *(DT_Shape *)shape);
+}
+
+void DT_DestroyObject(DT_ObjectHandle object)
+{
+ delete (DT_Object *)object;
+}
+
+void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin)
+{
+ ((DT_Object *)object)->setMargin(MT_Scalar(margin));
+}
+
+
+void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling)
+{
+ ((DT_Object *)object)->setScaling(MT_Vector3(scaling));
+}
+
+void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position)
+{
+ ((DT_Object *)object)->setPosition(MT_Point3(position));
+}
+
+void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation)
+{
+ ((DT_Object *)object)->setOrientation(MT_Quaternion(orientation));
+}
+
+
+void DT_SetMatrixf(DT_ObjectHandle object, const float *m)
+{
+ ((DT_Object *)object)->setMatrix(m);
+}
+
+void DT_GetMatrixf(DT_ObjectHandle object, float *m)
+{
+ ((DT_Object *)object)->getMatrix(m);
+}
+
+void DT_SetMatrixd(DT_ObjectHandle object, const double *m)
+{
+ ((DT_Object *)object)->setMatrix(m);
+}
+void DT_GetMatrixd(DT_ObjectHandle object, double *m)
+{
+ ((DT_Object *)object)->getMatrix(m);
+}
+
+void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max)
+{
+ const MT_BBox& bbox = ((DT_Object *)object)->getBBox();
+ bbox.getMin().getValue(min);
+ bbox.getMax().getValue(max);
+}
+
+DT_Bool DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 vec)
+{
+ MT_Vector3 v;
+ DT_Bool result = intersect(*(DT_Object*)object1, *(DT_Object*)object2, v);
+ v.getValue(vec);
+ return result;
+}
+
+DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2)
+{
+ MT_Point3 p1, p2;
+
+ MT_Scalar result = closest_points(*(DT_Object *)object1,
+ *(DT_Object *)object2,
+ p1, p2);
+ p1.getValue(point1);
+ p2.getValue(point2);
+
+ return MT_sqrt(result);
+}
+
+DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point)
+{
+ MT_Point3 p1, p2;
+ MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ bool result = common_point(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
+
+ if (result)
+ {
+ p1.getValue(point);
+ }
+
+ return result;
+}
+
+DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2)
+{
+ MT_Point3 p1, p2;
+ MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ bool result = penetration_depth(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
+
+ if (result)
+ {
+ p1.getValue(point1);
+ p2.getValue(point2);
+ }
+
+ return result;
+}
+
+// Response
+
+DT_RespTableHandle DT_CreateRespTable()
+{
+ return (DT_RespTableHandle)new DT_RespTable;
+}
+
+void DT_DestroyRespTable(DT_RespTableHandle respTable)
+{
+ delete (DT_RespTable *)respTable;
+}
+
+DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable)
+{
+ return ((DT_RespTable *)respTable)->genResponseClass();
+}
+
+void DT_SetResponseClass(DT_RespTableHandle respTable, DT_ObjectHandle object,
+ DT_ResponseClass responseClass)
+{
+ ((DT_RespTable *)respTable)->setResponseClass(object, responseClass);
+}
+
+void DT_ClearResponseClass(DT_RespTableHandle respTable,
+ DT_ObjectHandle object)
+{
+ ((DT_RespTable *)respTable)->clearResponseClass(object);
+}
+
+void DT_CallResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ const DT_CollData *coll_data)
+{
+ const DT_ResponseList& responseList =
+ ((DT_RespTable *)respTable)->find(object1, object2);
+
+ if (responseList.getType() != DT_NO_RESPONSE)
+ {
+ responseList(((DT_Object *)object1)->getClientObject(),
+ ((DT_Object *)object2)->getClientObject(),
+ coll_data);
+ }
+}
+
+
+void DT_AddDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data)
+{
+ ((DT_RespTable *)respTable)->addDefault(DT_Response(response, type, client_data));
+}
+
+void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response)
+{
+ ((DT_RespTable *)respTable)->removeDefault(DT_Response(response));
+}
+
+void DT_AddClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data)
+{
+ ((DT_RespTable *)respTable)->addSingle(responseClass,
+ DT_Response(response, type, client_data));
+}
+
+void DT_RemoveClassResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass,
+ DT_ResponseCallback response)
+{
+ ((DT_RespTable *)respTable)->removeSingle(responseClass,
+ DT_Response(response));
+}
+
+void DT_AddPairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data)
+{
+ ((DT_RespTable *)respTable)->addPair(responseClass1, responseClass2,
+ DT_Response(response, type, client_data));
+}
+
+void DT_RemovePairResponse(DT_RespTableHandle respTable,
+ DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ DT_ResponseCallback response)
+{
+ ((DT_RespTable *)respTable)->removePair(responseClass1, responseClass2,
+ DT_Response(response));
+}
+
+
+// Runtime
+
+void DT_SetAccuracy(DT_Scalar max_error)
+{
+ if (max_error > MT_Scalar(0.0))
+ {
+ DT_Accuracy::setAccuracy(MT_Scalar(max_error));
+ }
+}
+
+void DT_SetTolerance(DT_Scalar tol_error)
+{
+ if (tol_error > MT_Scalar(0.0))
+ {
+ DT_Accuracy::setTolerance(MT_Scalar(tol_error));
+ }
+}
+
+DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable)
+{
+ return ((DT_Scene *)scene)->handleCollisions((DT_RespTable *)respTable);
+}
+
+void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal)
+{
+ DT_Scalar lambda = max_param;
+
+ void *client_object = ((DT_Scene *)scene)->rayCast(ignore_client, source, target,
+ lambda, normal);
+ if (client_object)
+ {
+ *param = lambda;
+ }
+ return client_object;
+}
+
+DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar max_param, DT_Scalar *param, DT_Vector3 hit_normal)
+{
+ MT_Scalar lambda = MT_Scalar(max_param);
+ MT_Vector3 normal;
+
+ bool result = ((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target),
+ lambda, normal);
+
+ if (result)
+ {
+ *param = lambda;
+ normal.getValue(hit_normal);
+ }
+ return result;
+}
+
diff --git a/extern/solid/src/DT_Encounter.cpp b/extern/solid/src/DT_Encounter.cpp
new file mode 100644
index 00000000000..36de33154a3
--- /dev/null
+++ b/extern/solid/src/DT_Encounter.cpp
@@ -0,0 +1,111 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_RespTable.h"
+#include "DT_Encounter.h"
+#include "DT_Object.h"
+#include "GEN_MinMax.h"
+
+DT_Bool DT_Encounter::exactTest(const DT_RespTable *respTable, int& count) const
+{
+ const DT_ResponseList& responseList = respTable->find(m_obj_ptr1, m_obj_ptr2);
+
+ switch (responseList.getType())
+ {
+ case DT_BROAD_RESPONSE:
+ return (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2)) ?
+ responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), 0) :
+ responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), 0);
+ case DT_SIMPLE_RESPONSE:
+ if (intersect(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis))
+ {
+ ++count;
+ return (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2)) ?
+ responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), 0) :
+ responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), 0);
+
+ }
+ break;
+ case DT_WITNESSED_RESPONSE: {
+ MT_Point3 p1, p2;
+
+ if (common_point(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis, p1, p2))
+ {
+ ++count;
+ if (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2))
+ {
+ DT_CollData coll_data;
+
+ p1.getValue(coll_data.point1);
+ p2.getValue(coll_data.point2);
+
+ return responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), &coll_data);
+ }
+ else
+ {
+ DT_CollData coll_data;
+
+ p1.getValue(coll_data.point2);
+ p2.getValue(coll_data.point1);
+
+ return responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), &coll_data);
+ }
+ }
+ break;
+ }
+ case DT_DEPTH_RESPONSE: {
+ MT_Point3 p1, p2;
+
+ if (penetration_depth(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis, p1, p2))
+ {
+ ++count;
+ if (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2))
+ {
+ DT_CollData coll_data;
+
+ p1.getValue(coll_data.point1);
+ p2.getValue(coll_data.point2);
+ (p2 - p1).getValue(coll_data.normal);
+
+ return responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), &coll_data);
+ }
+ else
+ {
+ DT_CollData coll_data;
+
+ p1.getValue(coll_data.point2);
+ p2.getValue(coll_data.point1);
+ (p1 - p2).getValue(coll_data.normal);
+
+ return responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), &coll_data);
+ }
+ }
+ break;
+ }
+ case DT_NO_RESPONSE:
+ break;
+ default:
+ assert(false);
+ }
+ return DT_CONTINUE;
+}
diff --git a/extern/solid/src/DT_Encounter.h b/extern/solid/src/DT_Encounter.h
new file mode 100644
index 00000000000..f20ea3936b0
--- /dev/null
+++ b/extern/solid/src/DT_Encounter.h
@@ -0,0 +1,84 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_ENCOUNTER_H
+#define DT_ENCOUNTER_H
+
+#include <set>
+
+#include "MT_Vector3.h"
+#include "DT_Object.h"
+#include "DT_Shape.h"
+
+class DT_RespTable;
+
+class DT_Encounter {
+public:
+ DT_Encounter() {}
+ DT_Encounter(DT_Object *obj_ptr1, DT_Object *obj_ptr2)
+ : m_sep_axis(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0))
+ {
+ assert(obj_ptr1 != obj_ptr2);
+ if (obj_ptr2->getType() < obj_ptr1->getType() ||
+ (obj_ptr2->getType() == obj_ptr1->getType() &&
+ obj_ptr2 < obj_ptr1))
+ {
+ m_obj_ptr1 = obj_ptr2;
+ m_obj_ptr2 = obj_ptr1;
+ }
+ else
+ {
+ m_obj_ptr1 = obj_ptr1;
+ m_obj_ptr2 = obj_ptr2;
+ }
+ }
+
+ DT_Object *first() const { return m_obj_ptr1; }
+ DT_Object *second() const { return m_obj_ptr2; }
+ const MT_Vector3& separatingAxis() const { return m_sep_axis; }
+
+ DT_Bool exactTest(const DT_RespTable *respTable, int& count) const;
+
+private:
+ DT_Object *m_obj_ptr1;
+ DT_Object *m_obj_ptr2;
+ mutable MT_Vector3 m_sep_axis;
+};
+
+inline bool operator<(const DT_Encounter& a, const DT_Encounter& b)
+{
+ return a.first() < b.first() ||
+ (a.first() == b.first() && a.second() < b.second());
+}
+
+
+
+inline std::ostream& operator<<(std::ostream& os, const DT_Encounter& a) {
+ return os << '(' << a.first() << ", " << a.second() << ')';
+}
+
+
+
+typedef std::set<DT_Encounter> DT_EncounterTable;
+
+#endif
diff --git a/extern/solid/src/DT_Object.cpp b/extern/solid/src/DT_Object.cpp
new file mode 100644
index 00000000000..ed43a7bdaf2
--- /dev/null
+++ b/extern/solid/src/DT_Object.cpp
@@ -0,0 +1,276 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Object.h"
+#include "DT_AlgoTable.h"
+#include "DT_Convex.h"
+#include "DT_Complex.h"
+#include "DT_LineSegment.h"
+#include "DT_Transform.h"
+#include "DT_Minkowski.h"
+#include "DT_Sphere.h"
+
+void DT_Object::setBBox()
+{
+ m_bbox = m_shape.bbox(m_xform, m_margin);
+ DT_Vector3 min, max;
+ m_bbox.getMin().getValue(min);
+ m_bbox.getMax().getValue(max);
+
+ T_ProxyList::const_iterator it;
+ for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
+ {
+ BP_SetBBox(*it, min, max);
+ }
+}
+
+bool DT_Object::ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& lambda, MT_Vector3& normal) const
+{
+ MT_Transform inv_xform = m_xform.inverse();
+ MT_Point3 local_source = inv_xform(source);
+ MT_Point3 local_target = inv_xform(target);
+ MT_Vector3 local_normal;
+
+ bool result = m_shape.ray_cast(local_source, local_target, lambda, local_normal);
+
+ if (result)
+ {
+ normal = local_normal * inv_xform.getBasis();
+ MT_Scalar len = normal.length();
+ if (len > MT_Scalar(0.0))
+ {
+ normal /= len;
+ }
+ }
+
+ return result;
+}
+
+
+typedef AlgoTable<Intersect> IntersectTable;
+typedef AlgoTable<Common_point> Common_pointTable;
+typedef AlgoTable<Penetration_depth> Penetration_depthTable;
+typedef AlgoTable<Closest_points> Closest_pointsTable;
+
+
+bool intersectConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v)
+{
+ DT_Transform ta(a2w, (const DT_Convex&)a);
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return intersect((a_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), v);
+}
+
+bool intersectComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v)
+{
+ if (a.getType() == COMPLEX)
+ {
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return intersect((const DT_Complex&)a, a2w, a_margin,
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), v);
+ }
+
+ bool r = intersectComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v);
+ v *= -1.;
+ return r;
+}
+
+bool intersectComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v)
+{
+ return intersect((const DT_Complex&)a, a2w, a_margin,
+ (const DT_Complex&)b, b2w, b_margin, v);
+}
+
+IntersectTable *intersectInitialize()
+{
+ IntersectTable *p = new IntersectTable;
+ p->addEntry(COMPLEX, COMPLEX, intersectComplexComplex);
+ p->addEntry(COMPLEX, CONVEX, intersectComplexConvex);
+ p->addEntry(CONVEX, CONVEX, intersectConvexConvex);
+ return p;
+}
+
+bool intersect(const DT_Object& a, const DT_Object& b, MT_Vector3& v)
+{
+ static IntersectTable *intersectTable = intersectInitialize();
+ Intersect intersect = intersectTable->lookup(a.getType(), b.getType());
+ return intersect(a.m_shape, a.m_xform, a.m_margin,
+ b.m_shape, b.m_xform, b.m_margin, v);
+}
+
+bool common_pointConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta(a2w, (const DT_Convex&)a);
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return common_point((a_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), v, pa, pb);
+}
+
+bool common_pointComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ if (a.getType() == COMPLEX)
+ {
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return common_point((const DT_Complex&)a, a2w, a_margin,
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), v, pa, pb);
+ }
+
+ bool r = common_pointComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v, pb, pa);
+ v *= -1.;
+ return r;
+}
+
+bool common_pointComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ return common_point((const DT_Complex&)a, a2w, a_margin,
+ (const DT_Complex&)b, b2w, b_margin, v, pa, pb);
+}
+
+Common_pointTable *common_pointInitialize()
+{
+ Common_pointTable *p = new Common_pointTable;
+ p->addEntry(COMPLEX, COMPLEX, common_pointComplexComplex);
+ p->addEntry(COMPLEX, CONVEX, common_pointComplexConvex);
+ p->addEntry(CONVEX, CONVEX, common_pointConvexConvex);
+ return p;
+}
+
+bool common_point(const DT_Object& a, const DT_Object& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ static Common_pointTable *common_pointTable = common_pointInitialize();
+ Common_point common_point = common_pointTable->lookup(a.getType(), b.getType());
+ return common_point(a.m_shape, a.m_xform, a.m_margin,
+ b.m_shape, b.m_xform, b.m_margin, v, pa, pb);
+}
+
+
+
+bool penetration_depthConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ return hybrid_penetration_depth(DT_Transform(a2w, (const DT_Convex&)a), a_margin,
+ DT_Transform(b2w, (const DT_Convex&)b), b_margin, v, pa, pb);
+}
+
+bool penetration_depthComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ if (a.getType() == COMPLEX)
+ return penetration_depth((const DT_Complex&)a, a2w, a_margin,
+ DT_Transform(b2w, (const DT_Convex&)b), b_margin, v, pa, pb);
+
+ bool r = penetration_depthComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v, pb, pa);
+ v *= -1.;
+ return r;
+}
+
+bool penetration_depthComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ return penetration_depth((const DT_Complex&)a, a2w, a_margin, (const DT_Complex&)b, b2w, b_margin, v, pa, pb);
+}
+
+Penetration_depthTable *penetration_depthInitialize()
+{
+ Penetration_depthTable *p = new Penetration_depthTable;
+ p->addEntry(COMPLEX, COMPLEX, penetration_depthComplexComplex);
+ p->addEntry(COMPLEX, CONVEX, penetration_depthComplexConvex);
+ p->addEntry(CONVEX, CONVEX, penetration_depthConvexConvex);
+ return p;
+}
+
+bool penetration_depth(const DT_Object& a, const DT_Object& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ static Penetration_depthTable *penetration_depthTable = penetration_depthInitialize();
+ Penetration_depth penetration_depth = penetration_depthTable->lookup(a.getType(), b.getType());
+ return penetration_depth(a.m_shape, a.m_xform, a.m_margin,
+ b.m_shape, b.m_xform, b.m_margin, v, pa, pb);
+}
+
+
+MT_Scalar closest_pointsConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta(a2w, (const DT_Convex&)a);
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return closest_points((a_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), MT_INFINITY, pa, pb);
+}
+
+MT_Scalar closest_pointsComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ if (a.getType() == COMPLEX)
+ {
+ DT_Transform tb(b2w, (const DT_Convex&)b);
+ return closest_points((const DT_Complex&)a, a2w, a_margin,
+ (b_margin > MT_Scalar(0.0) ? static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast<const DT_Convex&>(tb)), pa, pb);
+ }
+
+ return closest_pointsComplexConvex(b, b2w, b_margin, a, a2w, a_margin, pb, pa);
+}
+
+MT_Scalar closest_pointsComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ return closest_points((const DT_Complex&)a, a2w, a_margin,
+ (const DT_Complex&)b, b2w, b_margin, pa, pb);
+}
+
+Closest_pointsTable *closest_pointsInitialize()
+{
+ Closest_pointsTable *p = new Closest_pointsTable;
+ p->addEntry(COMPLEX, COMPLEX, closest_pointsComplexComplex);
+ p->addEntry(COMPLEX, CONVEX, closest_pointsComplexConvex);
+ p->addEntry(CONVEX, CONVEX, closest_pointsConvexConvex);
+ return p;
+}
+
+MT_Scalar closest_points(const DT_Object& a, const DT_Object& b,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ static Closest_pointsTable *closest_pointsTable = closest_pointsInitialize();
+ Closest_points closest_points = closest_pointsTable->lookup(a.getType(), b.getType());
+ return closest_points(a.m_shape, a.m_xform, a.m_margin,
+ b.m_shape, b.m_xform, b.m_margin, pa, pb);
+}
+
diff --git a/extern/solid/src/DT_Object.h b/extern/solid/src/DT_Object.h
new file mode 100644
index 00000000000..78beee2ab57
--- /dev/null
+++ b/extern/solid/src/DT_Object.h
@@ -0,0 +1,157 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_OBJECT_H
+#define DT_OBJECT_H
+
+#include <vector>
+
+#include "SOLID.h"
+#include "SOLID_broad.h"
+
+#include "MT_Transform.h"
+#include "MT_Quaternion.h"
+#include "MT_BBox.h"
+#include "DT_Shape.h"
+
+class DT_Convex;
+
+class DT_Object {
+public:
+ DT_Object(void *client_object, const DT_Shape& shape) :
+ m_client_object(client_object),
+ m_shape(shape),
+ m_margin(MT_Scalar(0.0))
+ {
+ m_xform.setIdentity();
+ setBBox();
+ }
+
+ void setMargin(MT_Scalar margin)
+ {
+ m_margin = margin;
+ setBBox();
+ }
+
+ void setScaling(const MT_Vector3& scaling)
+ {
+ m_xform.scale(scaling);
+ setBBox();
+ }
+
+ void setPosition(const MT_Point3& pos)
+ {
+ m_xform.setOrigin(pos);
+ setBBox();
+ }
+
+ void setOrientation(const MT_Quaternion& orn)
+ {
+ m_xform.setRotation(orn);
+ setBBox();
+ }
+
+ void setMatrix(const float *m)
+ {
+ m_xform.setValue(m);
+ assert(m_xform.getBasis().determinant() != MT_Scalar(0.0));
+ setBBox();
+ }
+
+ void setMatrix(const double *m)
+ {
+ m_xform.setValue(m);
+ assert(m_xform.getBasis().determinant() != MT_Scalar(0.0));
+ setBBox();
+ }
+
+ void getMatrix(float *m) const
+ {
+ m_xform.getValue(m);
+ }
+
+ void getMatrix(double *m) const
+ {
+ m_xform.getValue(m);
+ }
+
+ void setBBox();
+
+ const MT_BBox& getBBox() const { return m_bbox; }
+
+ DT_ResponseClass getResponseClass() const { return m_responseClass; }
+
+ void setResponseClass(DT_ResponseClass responseClass)
+ {
+ m_responseClass = responseClass;
+ }
+
+ DT_ShapeType getType() const { return m_shape.getType(); }
+
+ void *getClientObject() const { return m_client_object; }
+
+ bool ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const;
+
+ void addProxy(BP_ProxyHandle proxy) { m_proxies.push_back(proxy); }
+
+ void removeProxy(BP_ProxyHandle proxy)
+ {
+ T_ProxyList::iterator it = std::find(m_proxies.begin(), m_proxies.end(), proxy);
+ if (it != m_proxies.end()) {
+ m_proxies.erase(it);
+ }
+ }
+
+
+ friend bool intersect(const DT_Object&, const DT_Object&, MT_Vector3& v);
+
+ friend bool common_point(const DT_Object&, const DT_Object&, MT_Vector3&,
+ MT_Point3&, MT_Point3&);
+
+ friend bool penetration_depth(const DT_Object&, const DT_Object&,
+ MT_Vector3&, MT_Point3&, MT_Point3&);
+
+ friend MT_Scalar closest_points(const DT_Object&, const DT_Object&,
+ MT_Point3&, MT_Point3&);
+
+private:
+ typedef std::vector<BP_ProxyHandle> T_ProxyList;
+
+ void *m_client_object;
+ DT_ResponseClass m_responseClass;
+ const DT_Shape& m_shape;
+ MT_Scalar m_margin;
+ MT_Transform m_xform;
+ T_ProxyList m_proxies;
+ MT_BBox m_bbox;
+};
+
+#endif
+
+
+
+
+
+
+
diff --git a/extern/solid/src/DT_RespTable.cpp b/extern/solid/src/DT_RespTable.cpp
new file mode 100644
index 00000000000..20fbfc06aac
--- /dev/null
+++ b/extern/solid/src/DT_RespTable.cpp
@@ -0,0 +1,184 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_RespTable.h"
+
+#include <assert.h>
+
+DT_ResponseList DT_RespTable::g_emptyResponseList;
+
+DT_RespTable::~DT_RespTable()
+{
+ DT_ResponseClass i;
+ for (i = 0; i < m_responseClass; ++i)
+ {
+ delete [] m_table[i];
+ }
+}
+
+DT_ResponseClass DT_RespTable::genResponseClass()
+{
+ DT_ResponseClass newClass = m_responseClass++;
+ DT_ResponseList *newList = new DT_ResponseList[m_responseClass];
+ assert(newList);
+ m_table.push_back(newList);
+ m_singleList.resize(m_responseClass);
+ DT_ResponseClass i;
+ for (i = 0; i < m_responseClass; ++i)
+ {
+ newList[i].append(m_default);
+ newList[i].append(m_singleList[i]);
+ }
+ return newClass;
+}
+
+void DT_RespTable::setResponseClass(void *object,
+ DT_ResponseClass responseClass)
+{
+ assert(responseClass < m_responseClass);
+ m_objectMap[object] = responseClass;
+}
+
+DT_ResponseClass DT_RespTable::getResponseClass(void *object) const
+{
+ T_ObjectMap::const_iterator it = m_objectMap.find(object);
+ assert(it != m_objectMap.end());
+ return (*it).second;
+}
+
+void DT_RespTable::clearResponseClass(void *object)
+{
+ m_objectMap.erase(object);
+}
+
+const DT_ResponseList& DT_RespTable::find(void *object1, void *object2) const
+{
+ T_ObjectMap::const_iterator it = m_objectMap.find(object1);
+ if (it != m_objectMap.end())
+ {
+ DT_ResponseClass responseClass1 = (*it).second;
+ it = m_objectMap.find(object2);
+ if (it != m_objectMap.end())
+ {
+ DT_ResponseClass responseClass2 = (*it).second;
+ if (responseClass1 < responseClass2)
+ {
+ std::swap(responseClass1, responseClass2);
+ }
+ return m_table[responseClass1][responseClass2];
+ }
+ }
+ return g_emptyResponseList;
+}
+
+void DT_RespTable::addDefault(const DT_Response& response)
+{
+ m_default.addResponse(response);
+ DT_ResponseClass i;
+ for (i = 0; i < m_responseClass; ++i)
+ {
+ DT_ResponseClass j;
+ for (j = 0; j <= i; ++j)
+ {
+ m_table[i][j].addResponse(response);
+ }
+ }
+}
+
+void DT_RespTable::removeDefault(const DT_Response& response)
+{
+ m_default.removeResponse(response);
+ DT_ResponseClass i;
+ for (i = 0; i < m_responseClass; ++i)
+ {
+ DT_ResponseClass j;
+ for (j = 0; j <= i; ++j)
+ {
+ m_table[i][j].removeResponse(response);
+ }
+ }
+}
+
+void DT_RespTable::addSingle(DT_ResponseClass responseClass,
+ const DT_Response& response)
+{
+ assert(responseClass < m_responseClass);
+ m_singleList[responseClass].addResponse(response);
+ DT_ResponseClass j;
+ for (j = 0; j < responseClass; ++j)
+ {
+ m_table[responseClass][j].addResponse(response);
+ }
+
+ DT_ResponseClass i;
+ for (i = responseClass; i < m_responseClass; ++i)
+ {
+ m_table[i][responseClass].addResponse(response);
+ }
+}
+
+void DT_RespTable::removeSingle(DT_ResponseClass responseClass,
+ const DT_Response& response)
+{
+ assert(responseClass < m_responseClass);
+ m_singleList[responseClass].removeResponse(response);
+ DT_ResponseClass j;
+ for (j = 0; j < responseClass; ++j)
+ {
+ m_table[responseClass][j].removeResponse(response);
+ }
+
+ DT_ResponseClass i;
+ for (i = responseClass; i < m_responseClass; ++i)
+ {
+ m_table[i][responseClass].removeResponse(response);
+ }
+}
+
+void DT_RespTable::addPair(DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ const DT_Response& response)
+{
+ assert(responseClass1 < m_responseClass);
+ assert(responseClass2 < m_responseClass);
+ if (responseClass1 < responseClass2)
+ {
+ std::swap(responseClass1, responseClass2);
+ }
+ m_table[responseClass1][responseClass2].addResponse(response);
+}
+
+
+void DT_RespTable::removePair(DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ const DT_Response& response)
+{
+ assert(responseClass1 < m_responseClass);
+ assert(responseClass2 < m_responseClass);
+ if (responseClass1 < responseClass2)
+ {
+ std::swap(responseClass1, responseClass2);
+ }
+ m_table[responseClass1][responseClass2].removeResponse(response);
+}
+
diff --git a/extern/solid/src/DT_RespTable.h b/extern/solid/src/DT_RespTable.h
new file mode 100644
index 00000000000..9a17f562937
--- /dev/null
+++ b/extern/solid/src/DT_RespTable.h
@@ -0,0 +1,139 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_RESPTABLE_H
+#define DT_RESPTABLE_H
+
+#include <algorithm>
+#include <vector>
+#include <list>
+#include <map>
+#include "GEN_MinMax.h"
+#include "DT_Response.h"
+
+class DT_ResponseList : public std::list<DT_Response> {
+public:
+ DT_ResponseList() : m_type(DT_NO_RESPONSE) {}
+
+ DT_ResponseType getType() const { return m_type; }
+
+ void addResponse(const DT_Response& response)
+ {
+ if (response.getType() != DT_NO_RESPONSE)
+ {
+ push_back(response);
+ GEN_set_max(m_type, response.getType());
+ }
+ }
+
+ void removeResponse(const DT_Response& response)
+ {
+ iterator it = std::find(begin(), end(), response);
+ if (it != end())
+ {
+ erase(it);
+ m_type = DT_NO_RESPONSE;
+ for (it = begin(); it != end(); ++it)
+ {
+ GEN_set_max(m_type, (*it).getType());
+ }
+ }
+ }
+
+ void append(const DT_ResponseList& responseList)
+ {
+ if (responseList.getType() != DT_NO_RESPONSE)
+ {
+ const_iterator it;
+ for (it = responseList.begin(); it != responseList.end(); ++it)
+ {
+ addResponse(*it);
+ }
+ }
+ }
+
+ DT_Bool operator()(void *a, void *b, const DT_CollData *coll_data) const
+ {
+ DT_Bool done = DT_CONTINUE;
+ const_iterator it;
+ for (it = begin(); !done && it != end(); ++it)
+ {
+ done = (*it)(a, b, coll_data);
+ }
+ return done;
+ }
+
+private:
+ DT_ResponseType m_type;
+};
+
+class DT_RespTable {
+private:
+ typedef std::map<void *, DT_ResponseClass> T_ObjectMap;
+ typedef std::vector<DT_ResponseList *> T_PairTable;
+ typedef std::vector<DT_ResponseList> T_SingleList;
+
+public:
+ DT_RespTable() : m_responseClass(0) {}
+
+ ~DT_RespTable();
+
+ DT_ResponseClass genResponseClass();
+
+ void setResponseClass(void *object, DT_ResponseClass responseClass);
+ DT_ResponseClass getResponseClass(void *object) const;
+
+ void clearResponseClass(void *object);
+
+ const DT_ResponseList& find(void *object1, void *object2) const;
+
+ void addDefault(const DT_Response& response);
+ void removeDefault(const DT_Response& response);
+
+ void addSingle(DT_ResponseClass responseClass,
+ const DT_Response& response);
+ void removeSingle(DT_ResponseClass responseClass,
+ const DT_Response& response);
+
+ void addPair(DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ const DT_Response& response);
+ void removePair(DT_ResponseClass responseClass1,
+ DT_ResponseClass responseClass2,
+ const DT_Response& response);
+
+private:
+ static DT_ResponseList g_emptyResponseList;
+
+ T_ObjectMap m_objectMap;
+ DT_ResponseClass m_responseClass;
+ T_PairTable m_table;
+ T_SingleList m_singleList;
+ DT_ResponseList m_default;
+};
+
+#endif
+
+
+
+
diff --git a/extern/solid/src/DT_Response.h b/extern/solid/src/DT_Response.h
new file mode 100644
index 00000000000..e58d9bb9944
--- /dev/null
+++ b/extern/solid/src/DT_Response.h
@@ -0,0 +1,63 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_RESPONSE_H
+#define DT_RESPONSE_H
+
+#include "SOLID.h"
+
+class DT_Response {
+public:
+ DT_Response(DT_ResponseCallback response = 0,
+ DT_ResponseType type = DT_NO_RESPONSE,
+ void *client_data = 0)
+ : m_response(response),
+ m_type(type),
+ m_client_data(client_data) {}
+
+ DT_ResponseType getType() const { return m_type; }
+
+ DT_Bool operator()(void *a, void *b, const DT_CollData *coll_data) const
+ {
+ return (*m_response)(m_client_data, a, b, coll_data);
+ }
+
+ friend bool operator==(const DT_Response& a, const DT_Response& b)
+ {
+ return a.m_response == b.m_response;
+ }
+
+ friend bool operator!=(const DT_Response& a, const DT_Response& b)
+ {
+ return a.m_response != b.m_response;
+ }
+
+private:
+ DT_ResponseCallback m_response;
+ DT_ResponseType m_type;
+ void *m_client_data;
+};
+
+#endif
+
+
diff --git a/extern/solid/src/DT_Scene.cpp b/extern/solid/src/DT_Scene.cpp
new file mode 100644
index 00000000000..56cea1633ca
--- /dev/null
+++ b/extern/solid/src/DT_Scene.cpp
@@ -0,0 +1,183 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Scene.h"
+#include "DT_Object.h"
+#include "DT_Convex.h"
+
+//#define DEBUG
+
+static void beginOverlap(void *client_data, void *object1, void *object2)
+{
+ DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
+ DT_EncounterTable *encounterTable = static_cast<DT_EncounterTable *>(client_data);
+
+#ifdef DEBUG
+ std::cout << "Begin: " << e << std::endl;
+#endif
+
+ encounterTable->insert(e);
+}
+
+
+static void endOverlap(void *client_data, void *object1, void *object2)
+{
+ DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
+ DT_EncounterTable *encounterTable = static_cast<DT_EncounterTable *>(client_data);
+
+#ifdef DEBUG
+ std::cout << "End: " << e << std::endl;
+#endif
+
+ assert(encounterTable->find(e) != encounterTable->end());
+ encounterTable->erase(e);
+}
+
+struct DT_RayCastData {
+ DT_RayCastData(const void *ignore)
+ : m_ignore(ignore)
+ {}
+
+ const void *m_ignore;
+ MT_Vector3 m_normal;
+};
+
+static bool objectRayCast(void *client_data,
+ void *object,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda)
+{
+ DT_RayCastData *data = static_cast<DT_RayCastData *>(client_data);
+ if (((DT_Object *)object)->getClientObject() != data->m_ignore)
+ {
+ MT_Scalar param = MT_Scalar(*lambda);
+
+ if (((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target),
+ param, data->m_normal))
+ {
+ *lambda = param;
+ return true;
+ }
+ }
+ return false;
+}
+
+DT_Scene::DT_Scene()
+ : m_broadphase(BP_CreateScene(&m_encounterTable, &beginOverlap, &endOverlap))
+{}
+
+DT_Scene::~DT_Scene()
+{
+ BP_DestroyScene(m_broadphase);
+}
+
+void DT_Scene::addObject(DT_Object &object)
+{
+ const MT_BBox& bbox = object.getBBox();
+ DT_Vector3 min, max;
+ bbox.getMin().getValue(min);
+ bbox.getMax().getValue(max);
+ BP_ProxyHandle proxy = BP_CreateProxy(m_broadphase, &object, min, max);
+
+#ifdef DEBUG
+ DT_EncounterTable::iterator it;
+ std::cout << "Add " << &object << ':';
+ for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) {
+ std::cout << ' ' << (*it);
+ }
+ std::cout << std::endl;
+#endif
+ object.addProxy(proxy);
+ m_objectList.push_back(std::make_pair(&object, proxy));
+}
+
+
+
+void DT_Scene::removeObject(DT_Object& object)
+{
+ T_ObjectList::iterator it = m_objectList.begin();
+
+ while (it != m_objectList.end() && &object != (*it).first)
+ {
+ ++it;
+ }
+
+ if (it != m_objectList.end())
+ {
+ object.removeProxy((*it).second);
+ BP_DestroyProxy(m_broadphase, (*it).second);
+ m_objectList.erase(it);
+
+#ifdef DEBUG
+ std::cout << "Remove " << &object << ':';
+ DT_EncounterTable::iterator it;
+ for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
+ {
+ std::cout << ' ' << (*it);
+ assert((*it).first() != &object &&
+ (*it).second() != &object);
+ }
+ std::cout << std::endl;
+#endif
+ }
+}
+
+
+
+int DT_Scene::handleCollisions(const DT_RespTable *respTable)
+{
+ int count = 0;
+
+ assert(respTable);
+
+ DT_EncounterTable::iterator it;
+ for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
+ {
+ if ((*it).exactTest(respTable, count))
+ {
+ break;
+ }
+
+ }
+ return count;
+}
+
+void *DT_Scene::rayCast(const void *ignore_client,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar& lambda, DT_Vector3 normal) const
+{
+ DT_RayCastData data(ignore_client);
+ DT_Object *object = (DT_Object *)BP_RayCast(m_broadphase,
+ &objectRayCast,
+ &data,
+ source, target,
+ &lambda);
+ if (object)
+ {
+ data.m_normal.getValue(normal);
+ return object->getClientObject();
+ }
+
+ return 0;
+}
diff --git a/extern/solid/src/DT_Scene.h b/extern/solid/src/DT_Scene.h
new file mode 100644
index 00000000000..9b061910312
--- /dev/null
+++ b/extern/solid/src/DT_Scene.h
@@ -0,0 +1,57 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_SCENE_H
+#define DT_SCENE_H
+
+#include <vector>
+
+#include "SOLID_broad.h"
+#include "DT_Encounter.h"
+
+class DT_Object;
+class DT_RespTable;
+
+class DT_Scene {
+public:
+ DT_Scene();
+ ~DT_Scene();
+
+ void addObject(DT_Object& object);
+ void removeObject(DT_Object& object);
+
+ int handleCollisions(const DT_RespTable *respTable);
+
+ void *rayCast(const void *ignore_client,
+ const DT_Vector3 source, const DT_Vector3 target,
+ DT_Scalar& lambda, DT_Vector3 normal) const;
+
+private:
+ typedef std::vector<std::pair<DT_Object *, BP_ProxyHandle> > T_ObjectList;
+
+ BP_SceneHandle m_broadphase;
+ T_ObjectList m_objectList;
+ DT_EncounterTable m_encounterTable;
+};
+
+#endif
diff --git a/extern/solid/src/Makefile b/extern/solid/src/Makefile
new file mode 100644
index 00000000000..e8ef7a606c9
--- /dev/null
+++ b/extern/solid/src/Makefile
@@ -0,0 +1,45 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+SOURCEDIR = extern/solid/src
+LIBNAME = solid
+DIR = $(OCGDIR)/extern/$(LIBNAME)
+DIRS = broad complex convex
+
+include nan_subdirs.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../include -I$(NAN_QHULL)/include
+CPPFLAGS += -Iconvex -Icomplex
+CPPFLAGS += -DQHULL -DUSE_DOUBLES
+
+include nan_compile.mk
+
diff --git a/extern/solid/src/broad/BP_C-api.cpp b/extern/solid/src/broad/BP_C-api.cpp
new file mode 100644
index 00000000000..43e1172927b
--- /dev/null
+++ b/extern/solid/src/broad/BP_C-api.cpp
@@ -0,0 +1,77 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "SOLID_broad.h"
+
+#include "BP_Scene.h"
+#include "BP_Proxy.h"
+
+BP_SceneHandle BP_CreateScene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap)
+{
+ return (BP_SceneHandle)new BP_Scene(client_data,
+ beginOverlap,
+ endOverlap);
+}
+
+
+void BP_DestroyScene(BP_SceneHandle scene)
+{
+ delete (BP_Scene *)scene;
+}
+
+
+BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, void *object,
+ const DT_Vector3 min, const DT_Vector3 max)
+{
+ return (BP_ProxyHandle)
+ ((BP_Scene *)scene)->createProxy(object, min, max);
+}
+
+
+void BP_DestroyProxy(BP_SceneHandle scene, BP_ProxyHandle proxy)
+{
+ ((BP_Scene *)scene)->destroyProxy((BP_Proxy *)proxy);
+}
+
+
+
+void BP_SetBBox(BP_ProxyHandle proxy, const DT_Vector3 min, const DT_Vector3 max)
+{
+ ((BP_Proxy *)proxy)->setBBox(min, max);
+}
+
+void *BP_RayCast(BP_SceneHandle scene,
+ BP_RayCastCallback objectRayCast,
+ void *client_data,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar *lambda)
+{
+ return ((BP_Scene *)scene)->rayCast(objectRayCast,
+ client_data,
+ source, target,
+ *lambda);
+}
+
diff --git a/extern/solid/src/broad/BP_Endpoint.h b/extern/solid/src/broad/BP_Endpoint.h
new file mode 100644
index 00000000000..8de6e67ce65
--- /dev/null
+++ b/extern/solid/src/broad/BP_Endpoint.h
@@ -0,0 +1,108 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef BP_ENDPOINT_H
+#define BP_ENDPOINT_H
+
+#include "SOLID_types.h"
+
+class BP_Proxy;
+
+class BP_Link {
+public:
+ BP_Link() {}
+ explicit BP_Link(BP_Proxy *proxy) :
+ m_proxy(proxy)
+ {}
+
+ DT_Index m_index;
+ DT_Count m_count;
+ BP_Proxy *m_proxy;
+};
+
+typedef unsigned int Uint32;
+
+class BP_Endpoint {
+public:
+ enum {
+ MINIMUM = 0x00000000,
+ MAXIMUM = 0x80000000,
+ TYPEBIT = 0x00000001
+ };
+
+ BP_Endpoint() {}
+ BP_Endpoint(DT_Scalar pos, Uint32 type, BP_Link *link)
+ : m_link(link)
+ {
+ setPos(pos, type);
+ }
+
+ DT_Scalar getPos() const { return m_pos; }
+ DT_Index& getIndex() const { return m_link->m_index; }
+ DT_Count& getCount() const { return m_link->m_count; }
+ BP_Proxy *getProxy() const { return m_link->m_proxy; }
+
+ DT_Index getEndIndex() const { return (m_link + 1)->m_index; }
+
+ Uint32 getType() const
+ {
+ return (m_bits & TYPEBIT) ? (~m_bits & MAXIMUM) : (m_bits & MAXIMUM);
+ }
+
+ void setPos(DT_Scalar pos, Uint32 type)
+ {
+ m_pos = pos;
+ if ((m_bits & MAXIMUM) == type)
+ {
+ m_bits &= ~TYPEBIT;
+ }
+ else
+ {
+ m_bits |= TYPEBIT;
+ }
+ }
+
+private:
+ union {
+ DT_Scalar m_pos;
+ Uint32 m_bits;
+ };
+ BP_Link *m_link;
+};
+
+inline bool operator<(const BP_Endpoint& a, const BP_Endpoint& b)
+{
+ return a.getPos() < b.getPos();
+}
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/extern/solid/src/broad/BP_EndpointList.cpp b/extern/solid/src/broad/BP_EndpointList.cpp
new file mode 100644
index 00000000000..aa094ffeb0a
--- /dev/null
+++ b/extern/solid/src/broad/BP_EndpointList.cpp
@@ -0,0 +1,237 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include <float.h>
+#include <algorithm>
+
+#include "BP_EndpointList.h"
+#include "BP_Scene.h"
+#include "BP_Proxy.h"
+#include "BP_ProxyList.h"
+
+DT_Index BP_EndpointList::stab(const BP_Endpoint& pos, BP_ProxyList& proxies) const
+{
+ DT_Index result = std::upper_bound(begin(), end(), pos) - begin();
+
+ if (result != 0)
+ {
+ DT_Index i = result - 1;
+ DT_Count count = (*this)[i].getCount();
+ while (count)
+ {
+ const BP_Endpoint& endpoint = (*this)[i];
+ if (endpoint.getType() == BP_Endpoint::MINIMUM &&
+ pos < (*this)[endpoint.getEndIndex()])
+ {
+ proxies.add(endpoint.getProxy());
+ --count;
+ }
+ assert(i != 0 || count == 0);
+ --i;
+ }
+ }
+ return result;
+}
+
+DT_Scalar BP_EndpointList::nextLambda(DT_Index& index,
+ DT_Scalar source,
+ DT_Scalar delta) const
+{
+ if (delta != 0.0f)
+ {
+ if (delta < 0.0f)
+ {
+ if (index != 0)
+ {
+ return ((*this)[--index].getPos() - source) / delta;
+ }
+ }
+ else
+ {
+ if (index != size())
+ {
+ return ((*this)[index++].getPos() - source) / delta;
+ }
+ }
+ }
+ return FLT_MAX;
+}
+
+
+void BP_EndpointList::range(const BP_Endpoint& min,
+ const BP_Endpoint& max,
+ DT_Index& first, DT_Index& last,
+ BP_ProxyList& proxies) const
+{
+ first = stab(min, proxies);
+ last = std::upper_bound(begin(), end(), max) - begin();
+
+ DT_Index i;
+ for (i = first; i != last; ++i)
+ {
+ const BP_Endpoint& endpoint = (*this)[i];
+ if (endpoint.getType() == BP_Endpoint::MINIMUM)
+ {
+ proxies.add(endpoint.getProxy());
+ }
+ }
+}
+
+void BP_EndpointList::addInterval(const BP_Endpoint& min,
+ const BP_Endpoint& max,
+ BP_ProxyList& proxies)
+{
+ assert(invariant());
+ DT_Index first, last;
+ range(min, max, first, last, proxies);
+ insert(begin() + last, max);
+ insert(begin() + first, min);
+ ++last;
+
+ (*this)[first].getCount() = first != 0 ? (*this)[first - 1].getCount() : 0;
+ (*this)[last].getCount() = (*this)[last - 1].getCount();
+
+
+ DT_Index i;
+ for (i = first; i != last; ++i)
+ {
+ ++(*this)[i].getCount();
+ (*this)[i].getIndex() = i;
+ }
+ for (; i != size(); ++i)
+ {
+ (*this)[i].getIndex() = i;
+ }
+
+ assert(invariant());
+}
+
+void BP_EndpointList::removeInterval(DT_Index first, DT_Index last,
+ BP_ProxyList& proxies)
+{
+ assert(invariant());
+
+ BP_Endpoint min = (*this)[first];
+ BP_Endpoint max = (*this)[last];
+
+ erase(begin() + last);
+ erase(begin() + first);
+ --last;
+
+ DT_Index i;
+ for (i = first; i != last; ++i)
+ {
+ --(*this)[i].getCount();
+ (*this)[i].getIndex() = i;
+ }
+ for (; i != size(); ++i)
+ {
+ (*this)[i].getIndex() = i;
+ }
+
+ range(min, max, first, last, proxies);
+
+ assert(invariant());
+}
+
+void BP_EndpointList::move(DT_Index index, DT_Scalar pos, Uint32 type,
+ BP_Scene& scene, T_Overlap overlap)
+{
+ assert(invariant());
+
+ BP_Endpoint endpoint = (*this)[index];
+ DT_Scalar delta = pos - endpoint.getPos();
+
+ if (delta != DT_Scalar(0.0))
+ {
+ endpoint.setPos(pos, type);
+ if (delta < DT_Scalar(0.0))
+ {
+ while (index != 0 && endpoint < (*this)[index - 1])
+ {
+ (*this)[index] = (*this)[index - 1];
+ (*this)[index].getIndex() = index;
+ encounters((*this)[index], endpoint, scene, overlap);
+ --index;
+ }
+ }
+ else
+ {
+ DT_Index last = size() - 1;
+ while (index != last && (*this)[index + 1] < endpoint)
+ {
+ (*this)[index] = (*this)[index + 1];
+ (*this)[index].getIndex() = index;
+ encounters(endpoint, (*this)[index], scene, overlap);
+ ++index;
+ }
+ }
+ (*this)[index] = endpoint;
+ (*this)[index].getIndex() = index;
+ }
+
+ assert(invariant());
+}
+
+void BP_EndpointList::encounters(const BP_Endpoint& a, const BP_Endpoint& b,
+ BP_Scene& scene, T_Overlap overlap)
+{
+ assert(a.getProxy() != b.getProxy());
+
+ if (a.getType() != b.getType())
+ {
+ if (a.getType() == BP_Endpoint::MAXIMUM)
+ {
+ if (overlap(*a.getProxy(), *b.getProxy()))
+ {
+ scene.callBeginOverlap(a.getProxy()->getObject(),
+ b.getProxy()->getObject());
+ }
+ ++a.getCount();
+ ++b.getCount();
+ }
+ else
+ {
+ if (overlap(*a.getProxy(), *b.getProxy()))
+ {
+ scene.callEndOverlap(a.getProxy()->getObject(),
+ b.getProxy()->getObject());
+ }
+ --a.getCount();
+ --b.getCount();
+ }
+ }
+ else
+ {
+ if (a.getType() == BP_Endpoint::MAXIMUM)
+ {
+ --a.getCount();
+ ++b.getCount();
+ }
+ else
+ {
+ ++a.getCount();
+ --b.getCount();
+ }
+ }
+}
diff --git a/extern/solid/src/broad/BP_EndpointList.h b/extern/solid/src/broad/BP_EndpointList.h
new file mode 100644
index 00000000000..6154991ed3d
--- /dev/null
+++ b/extern/solid/src/broad/BP_EndpointList.h
@@ -0,0 +1,109 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef BP_ENDPOINTLIST_H
+#define BP_ENDPOINTLIST_H
+
+//#define PARANOID
+
+#include <vector>
+
+#include "BP_Endpoint.h"
+#include "BP_ProxyList.h"
+
+class BP_Scene;
+
+typedef bool (*T_Overlap)(const BP_Proxy& a, const BP_Proxy& b);
+
+class BP_EndpointList : public std::vector<BP_Endpoint> {
+public:
+ BP_EndpointList() {}
+
+ DT_Index stab(const BP_Endpoint& pos, BP_ProxyList& proxies) const;
+
+ DT_Index stab(DT_Scalar pos, BP_ProxyList& proxies) const
+ {
+ return stab(BP_Endpoint(pos, BP_Endpoint::MINIMUM, 0), proxies);
+ }
+
+
+ void range(const BP_Endpoint& min, const BP_Endpoint& max,
+ DT_Index& first, DT_Index& last, BP_ProxyList& proxies) const;
+
+ void range(DT_Scalar lb, DT_Scalar ub, DT_Index& first, DT_Index& last, BP_ProxyList& proxies) const
+ {
+ range(BP_Endpoint(lb, BP_Endpoint::MINIMUM, 0),
+ BP_Endpoint(ub, BP_Endpoint::MAXIMUM, 0),
+ first, last, proxies);
+ }
+
+ void addInterval(const BP_Endpoint& min, const BP_Endpoint& max, BP_ProxyList& proxies);
+ void removeInterval(DT_Index first, DT_Index last, BP_ProxyList& proxies);
+
+ void move(DT_Index index, DT_Scalar pos, Uint32 type, BP_Scene& scene, T_Overlap overlap);
+
+ DT_Scalar nextLambda(DT_Index& index, DT_Scalar source, DT_Scalar target) const;
+
+
+private:
+ void encounters(const BP_Endpoint& a, const BP_Endpoint& b,
+ BP_Scene& scene, T_Overlap overlap);
+
+
+#ifdef PARANOID
+ bool invariant() const
+ {
+ DT_Count count = 0;
+ DT_Index i;
+ for (i = 0; i != size(); ++i)
+ {
+ const BP_Endpoint& endpoint = (*this)[i];
+
+ if (endpoint.getType() == BP_Endpoint::MINIMUM)
+ {
+ ++count;
+ }
+ else
+ {
+ --count;
+ }
+ if (endpoint.getCount() != count)
+ {
+ return false;
+ }
+ if (endpoint.getIndex() != i)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+#else
+ bool invariant() const { return true; }
+#endif
+
+};
+
+
+
+#endif
diff --git a/extern/solid/src/broad/BP_Proxy.cpp b/extern/solid/src/broad/BP_Proxy.cpp
new file mode 100644
index 00000000000..e8007df240d
--- /dev/null
+++ b/extern/solid/src/broad/BP_Proxy.cpp
@@ -0,0 +1,120 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include <new>
+
+#include "BP_Proxy.h"
+#include "BP_Scene.h"
+
+BP_Proxy::BP_Proxy(void *object,
+ BP_Scene& scene)
+ : m_object(object),
+ m_scene(scene)
+{
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ new (&m_interval[i]) BP_Interval(this);
+ }
+}
+
+void BP_Proxy::add(const DT_Vector3 min,
+ const DT_Vector3 max,
+ BP_ProxyList& proxies)
+{
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ m_scene.getList(i).addInterval(
+ BP_Endpoint(min[i], BP_Endpoint::MINIMUM, &m_interval[i].m_min),
+ BP_Endpoint(max[i], BP_Endpoint::MAXIMUM, &m_interval[i].m_max),
+ proxies);
+ }
+}
+
+void BP_Proxy::remove(BP_ProxyList& proxies)
+{
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ m_scene.getList(i).removeInterval(
+ m_interval[i].m_min.m_index,
+ m_interval[i].m_max.m_index,
+ proxies);
+ }
+}
+
+DT_Scalar BP_Proxy::getMin(int i) const
+{
+ return m_scene.getList(i)[m_interval[i].m_min.m_index].getPos();
+}
+
+DT_Scalar BP_Proxy::getMax(int i) const
+{
+ return m_scene.getList(i)[m_interval[i].m_max.m_index].getPos();
+}
+
+bool overlapXY(const BP_Proxy& a, const BP_Proxy& b)
+{
+ return a.getMin(0) <= b.getMax(0) && b.getMin(0) <= a.getMax(0) &&
+ a.getMin(1) <= b.getMax(1) && b.getMin(1) <= a.getMax(1);
+}
+
+bool overlapXZ(const BP_Proxy& a, const BP_Proxy& b)
+{
+ return a.getMin(0) <= b.getMax(0) && b.getMin(0) <= a.getMax(0) &&
+ a.getMin(2) <= b.getMax(2) && b.getMin(2) <= a.getMax(2);
+}
+
+bool overlapYZ(const BP_Proxy& a, const BP_Proxy& b)
+{
+ return a.getMin(1) <= b.getMax(1) && b.getMin(1) <= a.getMax(1) &&
+ a.getMin(2) <= b.getMax(2) && b.getMin(2) <= a.getMax(2);
+}
+
+void BP_Proxy::setBBox(const DT_Vector3 min, const DT_Vector3 max)
+{
+ static T_Overlap overlap[3] = { overlapYZ, overlapXZ, overlapXY };
+
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ if (min[i] > getMax(i))
+ {
+ m_scene.getList(i).move(m_interval[i].m_max.m_index, max[i],
+ BP_Endpoint::MAXIMUM, m_scene, overlap[i]);
+ m_scene.getList(i).move(m_interval[i].m_min.m_index, min[i],
+ BP_Endpoint::MINIMUM, m_scene, overlap[i]);
+ }
+ else
+ {
+ m_scene.getList(i).move(m_interval[i].m_min.m_index, min[i],
+ BP_Endpoint::MINIMUM, m_scene, overlap[i]);
+ m_scene.getList(i).move(m_interval[i].m_max.m_index, max[i],
+ BP_Endpoint::MAXIMUM, m_scene, overlap[i]);
+ }
+ }
+}
+
+
+
diff --git a/extern/solid/src/broad/BP_Proxy.h b/extern/solid/src/broad/BP_Proxy.h
new file mode 100644
index 00000000000..b4500ddca44
--- /dev/null
+++ b/extern/solid/src/broad/BP_Proxy.h
@@ -0,0 +1,78 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef BP_PROXY_H
+#define BP_PROXY_H
+
+#include "BP_Endpoint.h"
+#include "BP_ProxyList.h"
+
+class BP_Interval {
+public:
+ BP_Interval() {}
+ BP_Interval(BP_Proxy *proxy) :
+ m_min(proxy),
+ m_max(proxy)
+ {}
+
+ BP_Link m_min;
+ BP_Link m_max;
+};
+
+class BP_Scene;
+
+class BP_Proxy {
+public:
+ BP_Proxy(void *object, BP_Scene& scene);
+
+ void add(const DT_Vector3 min,
+ const DT_Vector3 max,
+ BP_ProxyList& proxies);
+
+ void remove(BP_ProxyList& proxies);
+
+ void setBBox(const DT_Vector3 min, const DT_Vector3 max);
+
+ void *getObject() { return m_object; }
+
+ DT_Scalar getMin(int i) const;
+ DT_Scalar getMax(int i) const;
+
+private:
+ BP_Interval m_interval[3];
+ void *m_object;
+ BP_Scene& m_scene;
+};
+
+inline bool BP_overlap(const BP_Proxy *a, const BP_Proxy *b)
+{
+ return a->getMin(0) <= b->getMax(0) && b->getMin(0) <= a->getMax(0) &&
+ a->getMin(1) <= b->getMax(1) && b->getMin(1) <= a->getMax(1) &&
+ a->getMin(2) <= b->getMax(2) && b->getMin(2) <= a->getMax(2);
+}
+
+#endif
+
+
+
+
diff --git a/extern/solid/src/broad/BP_ProxyList.h b/extern/solid/src/broad/BP_ProxyList.h
new file mode 100644
index 00000000000..2f449777d2d
--- /dev/null
+++ b/extern/solid/src/broad/BP_ProxyList.h
@@ -0,0 +1,69 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef BP_PROXYLIST_H
+#define BP_PROXYLIST_H
+
+#include <assert.h>
+
+#include <vector>
+#include <algorithm>
+#include <utility>
+
+class BP_Proxy;
+
+typedef std::pair<BP_Proxy *, unsigned int> BP_ProxyEntry;
+
+inline bool operator<(const BP_ProxyEntry& a, const BP_ProxyEntry& b)
+{
+ return a.first < b.first;
+}
+
+class BP_ProxyList : public std::vector<BP_ProxyEntry> {
+public:
+ BP_ProxyList(size_t n = 20) : std::vector<BP_ProxyEntry>(n) {}
+
+ iterator add(BP_Proxy *proxy)
+ {
+ BP_ProxyEntry entry = std::make_pair(proxy, (unsigned int)0);
+ iterator it = std::lower_bound(begin(), end(), entry);
+ if (it == end() || (*it).first != proxy)
+ {
+ it = insert(it, entry);
+ }
+ ++(*it).second;
+ return it;
+ }
+
+ void remove(BP_Proxy *proxy)
+ {
+ BP_ProxyEntry entry = std::make_pair(proxy, (unsigned int)0);
+ iterator it = std::lower_bound(begin(), end(), entry);
+ if (it != end() && (*it).first == proxy && --(*it).second == 0)
+ {
+ erase(it);
+ }
+ }
+};
+
+#endif
diff --git a/extern/solid/src/broad/BP_Scene.cpp b/extern/solid/src/broad/BP_Scene.cpp
new file mode 100644
index 00000000000..c0cd83ba311
--- /dev/null
+++ b/extern/solid/src/broad/BP_Scene.cpp
@@ -0,0 +1,151 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "BP_Scene.h"
+#include "BP_Proxy.h"
+
+#include <algorithm>
+
+BP_Proxy *BP_Scene::createProxy(void *object,
+ const DT_Vector3 min,
+ const DT_Vector3 max)
+{
+ BP_Proxy *proxy = new BP_Proxy(object, *this);
+
+ proxy->add(min, max, m_proxies);
+
+ BP_ProxyList::iterator it;
+ for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
+ {
+ if ((*it).second == 3)
+ {
+ callBeginOverlap(proxy->getObject(), (*it).first->getObject());
+ }
+ }
+
+ m_proxies.clear();
+
+ return proxy;
+}
+
+void BP_Scene::destroyProxy(BP_Proxy *proxy)
+{
+ proxy->remove(m_proxies);
+
+ BP_ProxyList::iterator it;
+ for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
+ {
+ if ((*it).second == 3)
+ {
+ callEndOverlap(proxy->getObject(), (*it).first->getObject());
+ }
+ }
+
+ m_proxies.clear();
+
+ delete proxy;
+}
+
+void *BP_Scene::rayCast(BP_RayCastCallback objectRayCast,
+ void *client_data,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar& lambda) const
+{
+ void *client_object = 0;
+
+ DT_Index index[3];
+ index[0] = m_endpointList[0].stab(source[0], m_proxies);
+ index[1] = m_endpointList[1].stab(source[1], m_proxies);
+ index[2] = m_endpointList[2].stab(source[2], m_proxies);
+
+ BP_ProxyList::iterator it;
+ for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
+ {
+ if ((*it).second == 3 &&
+ (*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
+ {
+ client_object = (*it).first->getObject();
+ }
+ }
+
+ DT_Vector3 delta;
+ delta[0] = target[0] - source[0];
+ delta[1] = target[1] - source[1];
+ delta[2] = target[2] - source[2];
+
+ DT_Vector3 lambdas;
+ lambdas[0] = m_endpointList[0].nextLambda(index[0], source[0], delta[0]);
+ lambdas[1] = m_endpointList[1].nextLambda(index[1], source[1], delta[1]);
+ lambdas[2] = m_endpointList[2].nextLambda(index[2], source[2], delta[2]);
+ int closest = lambdas[0] < lambdas[1] ? (lambdas[0] < lambdas[2] ? 0 : 2) : (lambdas[1] < lambdas[2] ? 1 : 2);
+
+ while (lambdas[closest] < lambda)
+ {
+ if (delta[closest] < 0.0f)
+ {
+ const BP_Endpoint& endpoint = m_endpointList[closest][index[closest]];
+
+ if (endpoint.getType() == BP_Endpoint::MAXIMUM)
+ {
+ it = m_proxies.add(endpoint.getProxy());
+ if ((*it).second == 3 &&
+ (*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
+ {
+ client_object = (*it).first->getObject();
+ }
+ }
+ else
+ {
+ m_proxies.remove(endpoint.getProxy());
+ }
+ }
+ else
+ {
+ const BP_Endpoint& endpoint = m_endpointList[closest][index[closest] - 1];
+
+ if (endpoint.getType() == BP_Endpoint::MINIMUM)
+ {
+ it = m_proxies.add(endpoint.getProxy());
+ if ((*it).second == 3 &&
+ (*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
+ {
+ client_object = (*it).first->getObject();
+ }
+ }
+ else
+ {
+ m_proxies.remove(endpoint.getProxy());
+ }
+ }
+
+ lambdas[closest] = m_endpointList[closest].nextLambda(index[closest], source[closest], delta[closest]);
+ closest = lambdas[0] < lambdas[1] ? (lambdas[0] < lambdas[2] ? 0 : 2) : (lambdas[1] < lambdas[2] ? 1 : 2);
+ }
+
+ m_proxies.clear();
+
+ return client_object;
+}
+
+
diff --git a/extern/solid/src/broad/BP_Scene.h b/extern/solid/src/broad/BP_Scene.h
new file mode 100644
index 00000000000..ef55374c43b
--- /dev/null
+++ b/extern/solid/src/broad/BP_Scene.h
@@ -0,0 +1,79 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef BP_SCENE_H
+#define BP_SCENE_H
+
+#include <SOLID_broad.h>
+
+#include "BP_EndpointList.h"
+#include "BP_ProxyList.h"
+
+class BP_Proxy;
+
+class BP_Scene {
+public:
+ BP_Scene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap)
+ : m_client_data(client_data),
+ m_beginOverlap(beginOverlap),
+ m_endOverlap(endOverlap),
+ m_proxies(20)
+ {}
+
+ ~BP_Scene() {}
+
+ BP_Proxy *createProxy(void *object,
+ const DT_Vector3 min,
+ const DT_Vector3 max);
+
+ void destroyProxy(BP_Proxy *proxy);
+
+ void *rayCast(BP_RayCastCallback objectRayCast,
+ void *client_data,
+ const DT_Vector3 source,
+ const DT_Vector3 target,
+ DT_Scalar& lambda) const;
+
+ void callBeginOverlap(void *object1, void *object2)
+ {
+ (*m_beginOverlap)(m_client_data, object1, object2);
+ }
+
+ void callEndOverlap(void *object1, void *object2)
+ {
+ (*m_endOverlap)(m_client_data, object1, object2);
+ }
+
+ BP_EndpointList& getList(int i) { return m_endpointList[i]; }
+
+private:
+ void *m_client_data;
+ BP_Callback m_beginOverlap;
+ BP_Callback m_endOverlap;
+ BP_EndpointList m_endpointList[3];
+ mutable BP_ProxyList m_proxies;
+};
+
+#endif
diff --git a/extern/solid/src/broad/Makefile b/extern/solid/src/broad/Makefile
new file mode 100644
index 00000000000..ce10e5f0bcf
--- /dev/null
+++ b/extern/solid/src/broad/Makefile
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = solid_broad
+DIR = $(OCGDIR)/extern/$(LIBNAME)
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
+CPPFLAGS += -DQHULL -DUSE_DOUBLES
+
+include nan_compile.mk
+
+
diff --git a/extern/solid/src/complex/DT_BBoxTree.cpp b/extern/solid/src/complex/DT_BBoxTree.cpp
new file mode 100644
index 00000000000..4f10f61f2e2
--- /dev/null
+++ b/extern/solid/src/complex/DT_BBoxTree.cpp
@@ -0,0 +1,90 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_BBoxTree.h"
+
+inline DT_CBox getBBox(int first, int last, const DT_CBox *boxes, const DT_Index *indices)
+{
+ assert(last - first >= 1);
+
+ DT_CBox bbox = boxes[indices[first]];
+ int i;
+ for (i = first; i < last; ++i)
+ {
+ bbox = bbox.hull(boxes[indices[i]]);
+ }
+
+ return bbox;
+}
+
+DT_BBoxNode::DT_BBoxNode(int first, int last, int& node, DT_BBoxNode *free_nodes, const DT_CBox *boxes, DT_Index *indices, const DT_CBox& bbox)
+{
+ assert(last - first >= 2);
+
+ int axis = bbox.longestAxis();
+ MT_Scalar abscissa = bbox.getCenter()[axis];
+ int i = first, mid = last;
+ while (i < mid)
+ {
+ if (boxes[indices[i]].getCenter()[axis] < abscissa)
+ {
+ ++i;
+ }
+ else
+ {
+ --mid;
+ std::swap(indices[i], indices[mid]);
+ }
+ }
+
+ if (mid == first || mid == last)
+ {
+ mid = (first + last) / 2;
+ }
+
+ m_lbox = getBBox(first, mid, boxes, indices);
+ m_rbox = getBBox(mid, last, boxes, indices);
+ m_flags = 0x0;
+
+ if (mid - first == 1)
+ {
+ m_flags |= LLEAF;
+ m_lchild = indices[first];
+ }
+ else
+ {
+ m_lchild = node++;
+ new(&free_nodes[m_lchild]) DT_BBoxNode(first, mid, node, free_nodes, boxes, indices, m_lbox);
+ }
+
+ if (last - mid == 1)
+ {
+ m_flags |= RLEAF;
+ m_rchild = indices[mid];
+ }
+ else
+ {
+ m_rchild = node++;
+ new(&free_nodes[m_rchild]) DT_BBoxNode(mid, last, node, free_nodes, boxes, indices, m_rbox);
+ }
+}
diff --git a/extern/solid/src/complex/DT_BBoxTree.h b/extern/solid/src/complex/DT_BBoxTree.h
new file mode 100644
index 00000000000..3d9da6e34ba
--- /dev/null
+++ b/extern/solid/src/complex/DT_BBoxTree.h
@@ -0,0 +1,540 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_BBOXTREE_H
+#define DT_BBOXTREE_H
+
+#include <new>
+#include <algorithm>
+
+#include "DT_Convex.h"
+#include "DT_CBox.h"
+
+
+class DT_BBoxTree {
+public:
+ enum NodeType { INTERNAL = 0, LEAF = 1 };
+
+ DT_BBoxTree() {}
+ DT_BBoxTree(const DT_CBox& cbox, DT_Index index, NodeType type)
+ : m_cbox(cbox),
+ m_index(index),
+ m_type(type)
+ {}
+
+ DT_CBox m_cbox;
+ DT_Index m_index;
+ NodeType m_type;
+};
+
+
+
+class DT_BBoxNode {
+public:
+ DT_BBoxNode() {}
+ DT_BBoxNode(int first, int last, int& node, DT_BBoxNode *free_nodes, const DT_CBox *boxes, DT_Index *indices, const DT_CBox& bbox);
+
+ void makeChildren(DT_BBoxTree& ltree, DT_BBoxTree& rtree) const;
+ void makeChildren(const DT_CBox& added, DT_BBoxTree& ltree, DT_BBoxTree& rtree) const;
+
+ DT_CBox hull() const { return m_lbox.hull(m_rbox); }
+
+ enum FlagType { LLEAF = 0x80, RLEAF = 0x40 };
+
+ DT_CBox m_lbox;
+ DT_CBox m_rbox;
+ DT_Index m_lchild;
+ DT_Index m_rchild;
+ unsigned char m_flags;
+};
+
+inline void DT_BBoxNode::makeChildren(DT_BBoxTree& ltree, DT_BBoxTree& rtree) const
+{
+ new (&ltree) DT_BBoxTree(m_lbox, m_lchild, (m_flags & LLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
+ new (&rtree) DT_BBoxTree(m_rbox, m_rchild, (m_flags & RLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
+
+}
+
+inline void DT_BBoxNode::makeChildren(const DT_CBox& added, DT_BBoxTree& ltree, DT_BBoxTree& rtree) const
+{
+ new (&ltree) DT_BBoxTree(m_lbox + added, m_lchild, (m_flags & LLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
+ new (&rtree) DT_BBoxTree(m_rbox + added, m_rchild, (m_flags & RLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
+}
+
+
+template <typename Shape>
+class DT_RootData {
+public:
+ DT_RootData(const DT_BBoxNode *nodes,
+ const Shape *leaves)
+ : m_nodes(nodes),
+ m_leaves(leaves)
+ {}
+
+ const DT_BBoxNode *m_nodes;
+ const Shape *m_leaves;
+};
+
+template <typename Shape1, typename Shape2>
+class DT_ObjectData : public DT_RootData<Shape1> {
+public:
+ DT_ObjectData(const DT_BBoxNode *nodes,
+ const Shape1 *leaves,
+ const MT_Transform& xform,
+ Shape2 plus)
+ : DT_RootData<Shape1>(nodes, leaves),
+ m_xform(xform),
+ m_inv_xform(xform.inverse()),
+ m_plus(plus),
+ m_added(computeCBox(plus, m_inv_xform))
+ {}
+
+ const MT_Transform& m_xform;
+ MT_Transform m_inv_xform;
+ Shape2 m_plus;
+ DT_CBox m_added;
+};
+
+template <typename Shape1, typename Shape2>
+class DT_Pack {
+public:
+ DT_Pack(const DT_ObjectData<Shape1, Shape2>& a, const DT_Convex& b)
+ : m_a(a),
+ m_b(b),
+ m_b_cbox(b.bbox(m_a.m_inv_xform))
+ {}
+
+ DT_ObjectData<Shape1, Shape2> m_a;
+ const DT_Convex& m_b;
+ DT_CBox m_b_cbox;
+};
+
+template <typename Shape1, typename Shape2>
+class DT_HybridPack : public DT_Pack<Shape1, Shape2> {
+public:
+ DT_HybridPack(const DT_ObjectData<Shape1, Shape2>& a, const DT_Convex& b, MT_Scalar margin)
+ : DT_Pack<Shape1, Shape2>(a, b),
+ m_margin(margin)
+ {
+ this->m_b_cbox += computeCBox(margin, this->m_a.m_inv_xform);
+ }
+
+ MT_Scalar m_margin;
+};
+
+template <typename Shape1, typename Shape2>
+class DT_DuoPack {
+public:
+ DT_DuoPack(const DT_ObjectData<Shape1, Shape2>& a, const DT_ObjectData<Shape1, Shape2>& b)
+ : m_a(a),
+ m_b(b)
+ {
+ m_b2a = a.m_inv_xform * b.m_xform;
+ m_a2b = b.m_inv_xform * a.m_xform;
+ m_abs_b2a = m_b2a.getBasis().absolute();
+ m_abs_a2b = m_a2b.getBasis().absolute();
+ }
+
+ DT_ObjectData<Shape1, Shape2> m_a, m_b;
+ MT_Transform m_b2a, m_a2b;
+ MT_Matrix3x3 m_abs_b2a, m_abs_a2b;
+};
+
+
+template <typename Shape>
+inline void refit(DT_BBoxNode& node, const DT_RootData<Shape>& rd)
+{
+ node.m_lbox = (node.m_flags & DT_BBoxNode::LLEAF) ?
+ computeCBox(rd.m_leaves[node.m_lchild]) :
+ rd.m_nodes[node.m_lchild].hull();
+ node.m_rbox = (node.m_flags & DT_BBoxNode::RLEAF) ?
+ computeCBox(rd.m_leaves[node.m_rchild]) :
+ rd.m_nodes[node.m_rchild].hull();
+}
+
+
+template <typename Shape>
+bool ray_cast(const DT_BBoxTree& a, const DT_RootData<Shape>& rd,
+ const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& lambda, MT_Vector3& normal)
+{
+ if (!a.m_cbox.overlapsLineSegment(source, source.lerp(target, lambda)))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF)
+ {
+ return ray_cast(rd, a.m_index, source, target, lambda, normal);
+ }
+ else
+ {
+ DT_BBoxTree ltree, rtree;
+ rd.m_nodes[a.m_index].makeChildren(ltree, rtree);
+
+ bool lresult = ray_cast(ltree, rd, source, target, lambda, normal);
+ bool rresult = ray_cast(rtree, rd, source, target, lambda, normal);
+ return lresult || rresult;
+ }
+}
+
+
+#ifdef STATISTICS
+int num_box_tests = 0;
+#endif
+
+template <typename Shape1, typename Shape2>
+inline bool intersect(const DT_CBox& a, const DT_CBox& b, const DT_DuoPack<Shape1, Shape2>& pack)
+{
+#ifdef STATISTICS
+ ++num_box_tests;
+#endif
+
+
+ MT_Vector3 abs_pos_b2a = (pack.m_b2a(b.getCenter()) - a.getCenter()).absolute();
+ MT_Vector3 abs_pos_a2b = (pack.m_a2b(a.getCenter()) - b.getCenter()).absolute();
+ return (a.getExtent()[0] + pack.m_abs_b2a[0].dot(b.getExtent()) >= abs_pos_b2a[0]) &&
+ (a.getExtent()[1] + pack.m_abs_b2a[1].dot(b.getExtent()) >= abs_pos_b2a[1]) &&
+ (a.getExtent()[2] + pack.m_abs_b2a[2].dot(b.getExtent()) >= abs_pos_b2a[2]) &&
+ (b.getExtent()[0] + pack.m_abs_a2b[0].dot(a.getExtent()) >= abs_pos_a2b[0]) &&
+ (b.getExtent()[1] + pack.m_abs_a2b[1].dot(a.getExtent()) >= abs_pos_a2b[1]) &&
+ (b.getExtent()[2] + pack.m_abs_a2b[2].dot(a.getExtent()) >= abs_pos_a2b[2]);
+}
+
+
+
+
+template <typename Shape1, typename Shape2>
+bool intersect(const DT_BBoxTree& a, const DT_Pack<Shape1, Shape2>& pack, MT_Vector3& v)
+{
+ if (!a.m_cbox.overlaps(pack.m_b_cbox))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF)
+ {
+ return intersect(pack, a.m_index, v);
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ return intersect(a_ltree, pack, v) || intersect(a_rtree, pack, v);
+ }
+}
+
+template <typename Shape1, typename Shape2>
+bool intersect(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack<Shape1, Shape2>& pack, MT_Vector3& v)
+{
+ if (!intersect(a.m_cbox, b.m_cbox, pack))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF)
+ {
+ return intersect(pack, a.m_index, b.m_index, v);
+ }
+ else if (a.m_type == DT_BBoxTree::LEAF ||
+ (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size()))
+ {
+ DT_BBoxTree b_ltree, b_rtree;
+ pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
+
+ return intersect(a, b_ltree, pack, v) || intersect(a, b_rtree, pack, v);
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ return intersect(a_ltree, b, pack, v) || intersect(a_rtree, b, pack, v);
+ }
+}
+
+template <typename Shape1, typename Shape2>
+bool common_point(const DT_BBoxTree& a, const DT_Pack<Shape1, Shape2>& pack,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ if (!a.m_cbox.overlaps(pack.m_b_cbox))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF)
+ {
+ return common_point(pack, a.m_index, v, pa, pb);
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ return common_point(a_ltree, pack, v, pa, pb) ||
+ common_point(a_rtree, pack, v, pa ,pb);
+ }
+}
+
+template <typename Shape1, typename Shape2>
+bool common_point(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack<Shape1, Shape2>& pack,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ if (!intersect(a.m_cbox, b.m_cbox, pack))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF)
+ {
+ return common_point(pack, a.m_index, b.m_index, v, pa, pb);
+ }
+ else if (a.m_type == DT_BBoxTree::LEAF ||
+ (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size()))
+ {
+ DT_BBoxTree b_ltree, b_rtree;
+ pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
+ return common_point(a, b_ltree, pack, v, pa, pb) ||
+ common_point(a, b_rtree, pack, v, pa, pb);
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ return common_point(a_ltree, b, pack, v, pa, pb) ||
+ common_point(a_rtree, b, pack, v, pa ,pb);
+ }
+}
+
+
+template <typename Shape1, typename Shape2>
+bool penetration_depth(const DT_BBoxTree& a, const DT_HybridPack<Shape1, Shape2>& pack,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb, MT_Scalar& max_pen_len)
+{
+ if (!a.m_cbox.overlaps(pack.m_b_cbox))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF)
+ {
+ if (penetration_depth(pack, a.m_index, v, pa, pb))
+ {
+ max_pen_len = pa.distance2(pb);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ if (penetration_depth(a_ltree, pack, v, pa, pb, max_pen_len))
+ {
+ MT_Vector3 rv;
+ MT_Point3 rpa, rpb;
+ MT_Scalar rmax_pen_len;
+ if (penetration_depth(a_rtree, pack, rv, rpa, rpb, rmax_pen_len) &&
+ (max_pen_len < rmax_pen_len))
+ {
+ max_pen_len = rmax_pen_len;
+ v = rv;
+ pa = rpa;
+ pb = rpb;
+ }
+ return true;
+ }
+ else
+ {
+ return penetration_depth(a_rtree, pack, v, pa, pb, max_pen_len);
+ }
+ }
+}
+
+template <typename Shape1, typename Shape2>
+bool penetration_depth(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack<Shape1, Shape2>& pack,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb, MT_Scalar& max_pen_len)
+{
+ if (!intersect(a.m_cbox, b.m_cbox, pack))
+ {
+ return false;
+ }
+
+ if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF)
+ {
+ if (penetration_depth(pack, a.m_index, b.m_index, v, pa, pb))
+ {
+ max_pen_len = pa.distance2(pb);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (a.m_type == DT_BBoxTree::LEAF ||
+ (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size()))
+ {
+ DT_BBoxTree b_ltree, b_rtree;
+ pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
+ if (penetration_depth(a, b_ltree, pack, v, pa, pb, max_pen_len))
+ {
+ MT_Point3 rpa, rpb;
+ MT_Scalar rmax_pen_len;
+ if (penetration_depth(a, b_rtree, pack, v, rpa, rpb, rmax_pen_len) &&
+ (max_pen_len < rmax_pen_len))
+ {
+ max_pen_len = rmax_pen_len;
+ pa = rpa;
+ pb = rpb;
+ }
+ return true;
+ }
+ else
+ {
+ return penetration_depth(a, b_rtree, pack, v, pa, pb, max_pen_len);
+ }
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ if (penetration_depth(a_ltree, b, pack, v, pa, pb, max_pen_len))
+ {
+ MT_Point3 rpa, rpb;
+ MT_Scalar rmax_pen_len;
+ if (penetration_depth(a_rtree, b, pack, v, rpa, rpb, rmax_pen_len) &&
+ (max_pen_len < rmax_pen_len))
+ {
+ max_pen_len = rmax_pen_len;
+ pa = rpa;
+ pb = rpb;
+ }
+ return true;
+ }
+ else
+ {
+ return penetration_depth(a_rtree, b, pack, v, pa, pb, max_pen_len);
+ }
+ }
+}
+
+
+// Returns a lower bound for the distance for quick rejection in closest_points
+inline MT_Scalar distance2(const DT_CBox& a, const MT_Transform& a2w,
+ const DT_CBox& b, const MT_Transform& b2w)
+{
+ MT_Vector3 v = b2w(b.getCenter()) - a2w(a.getCenter());
+ MT_Scalar dist2 = v.length2();
+ if (dist2 > MT_Scalar(0.0))
+ {
+ MT_Vector3 w = b2w(b.support(-v * b2w.getBasis())) - a2w(a.support(v * a2w.getBasis()));
+ MT_Scalar delta = v.dot(w);
+ return delta > MT_Scalar(0.0) ? delta * delta / dist2 : MT_Scalar(0.0);
+ }
+ return MT_Scalar(0.0);
+}
+
+
+template <typename Shape1, typename Shape2>
+MT_Scalar closest_points(const DT_BBoxTree& a, const DT_Pack<Shape1, Shape2>& pack,
+ MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb)
+{
+ if (a.m_type == DT_BBoxTree::LEAF)
+ {
+ return closest_points(pack, a.m_index, max_dist2, pa, pb);
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ MT_Scalar ldist2 = distance2(a_ltree.m_cbox, pack.m_a.m_xform, pack.m_b_cbox, pack.m_a.m_xform);
+ MT_Scalar rdist2 = distance2(a_rtree.m_cbox, pack.m_a.m_xform, pack.m_b_cbox, pack.m_a.m_xform);
+ if (ldist2 < rdist2)
+ {
+ MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a_ltree, pack, max_dist2, pa, pb) : MT_INFINITY;
+ GEN_set_min(max_dist2, dist2);
+ return rdist2 < max_dist2 ? GEN_min(dist2, closest_points(a_rtree, pack, max_dist2, pa, pb)) : dist2;
+ }
+ else
+ {
+ MT_Scalar dist2 = rdist2 < max_dist2 ? closest_points(a_rtree, pack, max_dist2, pa, pb) : MT_INFINITY;
+ GEN_set_min(max_dist2, dist2);
+ return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a_ltree, pack, max_dist2, pa, pb)) : dist2;
+ }
+ }
+}
+
+
+template <typename Shape1, typename Shape2>
+MT_Scalar closest_points(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack<Shape1, Shape2>& pack,
+ MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb)
+{
+ if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF)
+ {
+ return closest_points(pack, a.m_index, b.m_index, max_dist2, pa, pb);
+ }
+ else if (a.m_type == DT_BBoxTree::LEAF ||
+ (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size()))
+ {
+ DT_BBoxTree b_ltree, b_rtree;
+ pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
+ MT_Scalar ldist2 = distance2(a.m_cbox, pack.m_a.m_xform, b_ltree.m_cbox, pack.m_b.m_xform);
+ MT_Scalar rdist2 = distance2(a.m_cbox, pack.m_a.m_xform, b_rtree.m_cbox, pack.m_b.m_xform);
+ if (ldist2 < rdist2)
+ {
+ MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a, b_ltree, pack, max_dist2, pa, pb): MT_INFINITY;;
+ GEN_set_min(max_dist2, dist2);
+ return rdist2 < max_dist2 ? GEN_min(dist2, closest_points(a, b_rtree, pack, max_dist2, pa, pb)) : dist2;
+ }
+ else
+ {
+ MT_Scalar dist2 = rdist2 < max_dist2 ? closest_points(a, b_rtree, pack, max_dist2, pa, pb) : MT_INFINITY;;
+ GEN_set_min(max_dist2, dist2);
+ return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a, b_ltree, pack, max_dist2, pa, pb)) : dist2;
+ }
+ }
+ else
+ {
+ DT_BBoxTree a_ltree, a_rtree;
+ pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
+ MT_Scalar ldist2 = distance2(a_ltree.m_cbox, pack.m_a.m_xform, b.m_cbox, pack.m_b.m_xform);
+ MT_Scalar rdist2 = distance2(a_rtree.m_cbox, pack.m_a.m_xform, b.m_cbox, pack.m_b.m_xform);
+ if (ldist2 < rdist2)
+ {
+ MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a_ltree, b, pack, max_dist2, pa, pb) : MT_INFINITY;;
+ GEN_set_min(max_dist2, dist2);
+ return rdist2 < max_dist2 ? GEN_min(dist2,closest_points(a_rtree, b, pack, max_dist2, pa, pb)) : dist2;
+ }
+ else
+ {
+ MT_Scalar dist2 = rdist2 < max_dist2 ? closest_points(a_rtree, b, pack, max_dist2, pa, pb) : MT_INFINITY;
+ GEN_set_min(max_dist2, dist2);
+ return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a_ltree, b, pack, max_dist2, pa, pb)) : dist2;
+ }
+ }
+}
+
+#endif
+
diff --git a/extern/solid/src/complex/DT_CBox.h b/extern/solid/src/complex/DT_CBox.h
new file mode 100644
index 00000000000..7fc7c5df4db
--- /dev/null
+++ b/extern/solid/src/complex/DT_CBox.h
@@ -0,0 +1,134 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_CBOX_H
+#define DT_CBOX_H
+
+#include "MT_BBox.h"
+
+struct DT_CBox {
+ DT_CBox() {}
+ DT_CBox(const MT_Point3& center, const MT_Vector3& extent)
+ : m_center(center),
+ m_extent(extent)
+ {}
+
+ explicit DT_CBox(const MT_BBox& bbox) { set(bbox); }
+
+ const MT_Point3& getCenter() const { return m_center; }
+ const MT_Vector3& getExtent() const { return m_extent; }
+
+ void set(const MT_BBox& bbox)
+ {
+ m_center = bbox.getCenter();
+ m_extent = bbox.getExtent();
+ }
+
+ MT_BBox get() const
+ {
+ return MT_BBox(m_center - m_extent, m_center + m_extent);
+ }
+
+ MT_Scalar size() const
+ {
+ return GEN_max(GEN_max(m_extent[0], m_extent[1]), m_extent[2]);
+ }
+
+
+ DT_CBox& operator+=(const DT_CBox& box)
+ {
+ m_center += box.getCenter();
+ m_extent += box.getExtent();
+ return *this;
+ }
+
+ int longestAxis() const { return m_extent.closestAxis(); }
+
+ DT_CBox hull(const DT_CBox& b) const
+ {
+ return DT_CBox(this->get().hull(b.get()));
+ }
+
+ bool overlaps(const DT_CBox& b) const
+ {
+ return MT_abs(m_center[0] - b.m_center[0]) <= m_extent[0] + b.m_extent[0] &&
+ MT_abs(m_center[1] - b.m_center[1]) <= m_extent[1] + b.m_extent[1] &&
+ MT_abs(m_center[2] - b.m_center[2]) <= m_extent[2] + b.m_extent[2];
+ }
+
+ bool overlapsLineSegment(const MT_Point3& p, const MT_Point3& q) const
+ {
+ MT_Vector3 r = q - p;
+ MT_Vector3 r_abs = r.absolute();
+
+ if (!overlaps(DT_CBox(p + r * MT_Scalar(0.5), r_abs * MT_Scalar(0.5))))
+ {
+ return false;
+ }
+
+ MT_Vector3 s = p - m_center;
+
+ if (MT_abs(r[2] * s[1] - r[1] * s[2]) > r_abs[2] * m_extent[1] + r_abs[1] * m_extent[2])
+ {
+ return false;
+ }
+
+ if (MT_abs(r[0] * s[2] - r[2] * s[0]) > r_abs[0] * m_extent[2] + r_abs[2] * m_extent[0])
+ {
+ return false;
+ }
+
+ if (MT_abs(r[1] * s[0] - r[0] * s[1]) > r_abs[1] * m_extent[0] + r_abs[0] * m_extent[1])
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ MT_Point3 support(const MT_Vector3& v) const
+ {
+ return m_center + MT_Vector3(v[0] < MT_Scalar(0.0) ? -m_extent[0] : m_extent[0],
+ v[1] < MT_Scalar(0.0) ? -m_extent[1] : m_extent[1],
+ v[2] < MT_Scalar(0.0) ? -m_extent[2] : m_extent[2]);
+
+ }
+
+private:
+ MT_Point3 m_center;
+ MT_Vector3 m_extent;
+};
+
+inline DT_CBox operator+(const DT_CBox& b1, const DT_CBox& b2)
+{
+ return DT_CBox(b1.getCenter() + b2.getCenter(),
+ b1.getExtent() + b2.getExtent());
+}
+
+inline DT_CBox operator-(const DT_CBox& b1, const DT_CBox& b2)
+{
+ return DT_CBox(b1.getCenter() - b2.getCenter(),
+ b1.getExtent() + b2.getExtent());
+}
+
+#endif
diff --git a/extern/solid/src/complex/DT_Complex.cpp b/extern/solid/src/complex/DT_Complex.cpp
new file mode 100644
index 00000000000..023383a8427
--- /dev/null
+++ b/extern/solid/src/complex/DT_Complex.cpp
@@ -0,0 +1,327 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include <new>
+#include <fstream>
+
+#include "DT_Complex.h"
+#include "DT_Minkowski.h"
+#include "DT_Sphere.h"
+#include "DT_Transform.h"
+
+DT_Complex::DT_Complex(const DT_VertexBase *base)
+ : m_base(base),
+ m_count(0),
+ m_leaves(0),
+ m_nodes(0)
+{
+ assert(base);
+ base->addComplex(this);
+}
+
+
+DT_Complex::~DT_Complex()
+{
+ DT_Index i;
+ for (i = 0; i != m_count; ++i)
+ {
+ delete m_leaves[i];
+ }
+ delete [] m_leaves;
+ delete [] m_nodes;
+
+ m_base->removeComplex(this);
+ if (m_base->isOwner())
+ {
+ delete m_base;
+ }
+}
+
+void DT_Complex::finish(DT_Count n, const DT_Convex *p[])
+{
+ m_count = n;
+
+
+ assert(n >= 1);
+
+ m_leaves = new const DT_Convex *[n];
+ assert(m_leaves);
+
+ DT_CBox *boxes = new DT_CBox[n];
+ DT_Index *indices = new DT_Index[n];
+ assert(boxes);
+
+ DT_Index i;
+ for (i = 0; i != n; ++i)
+ {
+ m_leaves[i] = p[i];
+ boxes[i].set(p[i]->bbox());
+ indices[i] = i;
+ }
+
+ m_cbox = boxes[0];
+ for (i = 1; i != n; ++i)
+ {
+ m_cbox = m_cbox.hull(boxes[i]);
+ }
+
+ if (n == 1)
+ {
+ m_nodes = 0;
+ m_type = DT_BBoxTree::LEAF;
+ }
+ else
+ {
+ m_nodes = new DT_BBoxNode[n - 1];
+ assert(m_nodes);
+
+ int num_nodes = 0;
+ new(&m_nodes[num_nodes++]) DT_BBoxNode(0, n, num_nodes, m_nodes, boxes, indices, m_cbox);
+
+ assert(num_nodes == n - 1);
+
+ m_type = DT_BBoxTree::INTERNAL;
+ }
+
+ delete [] boxes;
+}
+
+
+MT_BBox DT_Complex::bbox(const MT_Transform& t, MT_Scalar margin) const
+{
+ MT_Matrix3x3 abs_b = t.getBasis().absolute();
+ MT_Point3 center = t(m_cbox.getCenter());
+ MT_Vector3 extent(margin + abs_b[0].dot(m_cbox.getExtent()),
+ margin + abs_b[1].dot(m_cbox.getExtent()),
+ margin + abs_b[2].dot(m_cbox.getExtent()));
+
+ return MT_BBox(center - extent, center + extent);
+}
+
+inline DT_CBox computeCBox(const DT_Convex *p)
+{
+ return DT_CBox(p->bbox());
+}
+
+inline DT_CBox computeCBox(MT_Scalar margin, const MT_Transform& xform)
+{
+ const MT_Matrix3x3& basis = xform.getBasis();
+ return DT_CBox(MT_Point3(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)),
+ MT_Vector3(basis[0].length() * margin,
+ basis[1].length() * margin,
+ basis[2].length() * margin));
+}
+
+void DT_Complex::refit()
+{
+ DT_RootData<const DT_Convex *> rd(m_nodes, m_leaves);
+ DT_Index i = m_count - 1;
+ while (i--)
+ {
+ ::refit(m_nodes[i], rd);
+ }
+ m_cbox = m_type == DT_BBoxTree::LEAF ? computeCBox(m_leaves[0]) : m_nodes[0].hull();
+}
+
+inline bool ray_cast(const DT_RootData<const DT_Convex *>& rd, DT_Index index, const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& lambda, MT_Vector3& normal)
+{
+ return rd.m_leaves[index]->ray_cast(source, target, lambda, normal);
+}
+
+bool DT_Complex::ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& lambda, MT_Vector3& normal) const
+{
+ DT_RootData<const DT_Convex *> rd(m_nodes, m_leaves);
+
+ return ::ray_cast(DT_BBoxTree(m_cbox, 0, m_type), rd, source, target, lambda, normal);
+}
+
+inline bool intersect(const DT_Pack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, MT_Vector3& v)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ return ::intersect((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ pack.m_b, v);
+}
+
+bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Vector3& v)
+{
+ DT_Pack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin), b);
+
+ return intersect(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v);
+}
+
+inline bool intersect(const DT_DuoPack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
+ MT_Scalar b_margin = pack.m_b.m_plus;
+ return ::intersect((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) :
+ static_cast<const DT_Convex&>(tb)),
+ v);
+}
+
+bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin, MT_Vector3& v)
+{
+ DT_DuoPack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin),
+ DT_ObjectData<const DT_Convex *, MT_Scalar>(b.m_nodes, b.m_leaves, b2w, b_margin));
+
+
+ return intersect(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
+ DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, v);
+}
+
+inline bool common_point(const DT_Pack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ return ::common_point((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ pack.m_b, v, pa, pb);
+}
+
+bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Pack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin), b);
+
+ return common_point(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v, pb, pa);
+}
+
+inline bool common_point(const DT_DuoPack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
+ MT_Scalar b_margin = pack.m_b.m_plus;
+ return ::common_point((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) :
+ static_cast<const DT_Convex&>(tb)),
+ v, pa, pb);
+}
+
+bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_DuoPack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin),
+ DT_ObjectData<const DT_Convex *, MT_Scalar>(b.m_nodes, b.m_leaves, b2w, b_margin));
+
+ return common_point(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
+ DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, v, pa, pb);
+}
+
+inline bool penetration_depth(const DT_HybridPack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ return ::hybrid_penetration_depth(ta, pack.m_a.m_plus, pack.m_b, pack.m_margin, v, pa, pb);
+}
+
+bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Scalar b_margin, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_HybridPack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin), b, b_margin);
+
+ MT_Scalar max_pen_len = MT_Scalar(0.0);
+ return penetration_depth(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v, pa, pb, max_pen_len);
+}
+
+inline bool penetration_depth(const DT_DuoPack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
+ return ::hybrid_penetration_depth(ta, pack.m_a.m_plus, tb, pack.m_a.m_plus, v, pa, pb);
+}
+
+bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_DuoPack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin),
+ DT_ObjectData<const DT_Convex *, MT_Scalar>(b.m_nodes, b.m_leaves, b2w, b_margin));
+
+ MT_Scalar max_pen_len = MT_Scalar(0.0);
+ return penetration_depth(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
+ DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, v, pa, pb, max_pen_len);
+}
+
+
+
+inline MT_Scalar closest_points(const DT_Pack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ return ::closest_points((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ pack.m_b, max_dist2, pa, pb);
+}
+
+MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Pack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin), b);
+
+ return closest_points(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, MT_INFINITY, pa, pb);
+}
+
+inline MT_Scalar closest_points(const DT_DuoPack<const DT_Convex *, MT_Scalar>& pack, DT_Index a_index, DT_Index b_index, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
+ MT_Scalar a_margin = pack.m_a.m_plus;
+ DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
+ MT_Scalar b_margin = pack.m_b.m_plus;
+ return ::closest_points((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(ta, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(ta)),
+ (b_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(tb, DT_Sphere(b_margin))) :
+ static_cast<const DT_Convex&>(tb)), max_dist2, pa, pb);
+}
+
+MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ DT_DuoPack<const DT_Convex *, MT_Scalar> pack(DT_ObjectData<const DT_Convex *, MT_Scalar>(a.m_nodes, a.m_leaves, a2w, a_margin),
+ DT_ObjectData<const DT_Convex *, MT_Scalar>(b.m_nodes, b.m_leaves, b2w, b_margin));
+
+ return closest_points(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
+ DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, MT_INFINITY, pa, pb);
+}
+
+
diff --git a/extern/solid/src/complex/DT_Complex.h b/extern/solid/src/complex/DT_Complex.h
new file mode 100644
index 00000000000..ae08a05d4c9
--- /dev/null
+++ b/extern/solid/src/complex/DT_Complex.h
@@ -0,0 +1,94 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_COMPLEX_H
+#define DT_COMPLEX_H
+
+#include <algorithm>
+
+#include "MT_Transform.h"
+#include "DT_VertexBase.h"
+
+#include "DT_Shape.h"
+#include "DT_CBox.h"
+#include "DT_BBoxTree.h"
+
+class DT_Convex;
+
+class DT_Complex : public DT_Shape {
+public:
+ DT_Complex(const DT_VertexBase *base);
+ virtual ~DT_Complex();
+
+ void finish(DT_Count n, const DT_Convex *p[]);
+
+ virtual DT_ShapeType getType() const { return COMPLEX; }
+
+ virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin) const;
+
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& lambda, MT_Vector3& normal) const;
+
+ void refit();
+
+
+ friend bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Vector3& v);
+
+ friend bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v);
+
+ friend bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+ friend bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+ friend bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Scalar b_margin, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+ friend bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+ friend MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Point3& pa, MT_Point3& pb);
+
+ friend MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3& pa, MT_Point3& pb);
+
+ const DT_VertexBase *m_base;
+ DT_Count m_count;
+ const DT_Convex **m_leaves;
+ DT_BBoxNode *m_nodes;
+ DT_CBox m_cbox;
+ DT_BBoxTree::NodeType m_type;
+};
+
+#endif
+
+
+
diff --git a/extern/solid/src/complex/Makefile b/extern/solid/src/complex/Makefile
new file mode 100644
index 00000000000..e8df4df51a3
--- /dev/null
+++ b/extern/solid/src/complex/Makefile
@@ -0,0 +1,42 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = solid_complex
+DIR = $(OCGDIR)/extern/$(LIBNAME)
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
+CPPFLAGS += -I../convex
+CPPFLAGS += -DQHULL -DUSE_DOUBLES
+
+include nan_compile.mk
+
+
diff --git a/extern/solid/src/convex/DT_Accuracy.cpp b/extern/solid/src/convex/DT_Accuracy.cpp
new file mode 100644
index 00000000000..113275b0dbd
--- /dev/null
+++ b/extern/solid/src/convex/DT_Accuracy.cpp
@@ -0,0 +1,30 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Accuracy.h"
+
+static const MT_Scalar rel_error = MT_Scalar(1.0e-3);
+
+MT_Scalar DT_Accuracy::rel_error2 = rel_error * rel_error;
+MT_Scalar DT_Accuracy::depth_tolerance = MT_Scalar(1.0) + MT_Scalar(2.0) * rel_error;
+MT_Scalar DT_Accuracy::tol_error = MT_EPSILON;
diff --git a/extern/solid/src/convex/DT_Accuracy.h b/extern/solid/src/convex/DT_Accuracy.h
new file mode 100644
index 00000000000..9759a6fd4c5
--- /dev/null
+++ b/extern/solid/src/convex/DT_Accuracy.h
@@ -0,0 +1,47 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_ACCURACY_H
+#define DT_ACCURACY_H
+
+#include "MT_Scalar.h"
+
+class DT_Accuracy {
+public:
+ static MT_Scalar rel_error2; // squared relative error in the computed distance
+ static MT_Scalar depth_tolerance; // terminate EPA if upper_bound <= depth_tolerance * dist2
+ static MT_Scalar tol_error; // error tolerance if the distance is almost zero
+
+ static void setAccuracy(MT_Scalar rel_error)
+ {
+ rel_error2 = rel_error * rel_error;
+ depth_tolerance = MT_Scalar(1.0) + MT_Scalar(2.0) * rel_error;
+ }
+
+ static void setTolerance(MT_Scalar epsilon)
+ {
+ tol_error = epsilon;
+ }
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Array.h b/extern/solid/src/convex/DT_Array.h
new file mode 100644
index 00000000000..1694f884e53
--- /dev/null
+++ b/extern/solid/src/convex/DT_Array.h
@@ -0,0 +1,75 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_ARRAY_H
+#define DT_ARRAY_H
+
+#if defined (__sgi)
+#include <assert.h>
+#else
+#include <cassert>
+#endif
+
+template <typename Data, typename Size = size_t>
+class DT_Array {
+public:
+ DT_Array()
+ : m_count(0),
+ m_data(0)
+ {}
+
+ explicit DT_Array(Size count)
+ : m_count(count),
+ m_data(new Data[count])
+ {
+ assert(m_data);
+ }
+
+ DT_Array(Size count, const Data *data)
+ : m_count(count),
+ m_data(new Data[count])
+ {
+ assert(m_data);
+ std::copy(&data[0], &data[count], m_data);
+ }
+
+ ~DT_Array()
+ {
+ delete [] m_data;
+ }
+
+ const Data& operator[](int i) const { return m_data[i]; }
+ Data& operator[](int i) { return m_data[i]; }
+
+ Size size() const { return m_count; }
+
+private:
+ DT_Array(const DT_Array&);
+ DT_Array& operator=(const DT_Array&);
+
+ Size m_count;
+ Data *m_data;
+};
+
+#endif
+
diff --git a/extern/solid/src/convex/DT_Box.cpp b/extern/solid/src/convex/DT_Box.cpp
new file mode 100644
index 00000000000..0b46f566fe8
--- /dev/null
+++ b/extern/solid/src/convex/DT_Box.cpp
@@ -0,0 +1,112 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Box.h"
+
+MT_Scalar DT_Box::supportH(const MT_Vector3& v) const
+{
+ return v.absolute().dot(m_extent);
+}
+
+MT_Point3 DT_Box::support(const MT_Vector3& v) const
+{
+ return MT_Point3(v[0] < MT_Scalar(0.0) ? -m_extent[0] : m_extent[0],
+ v[1] < MT_Scalar(0.0) ? -m_extent[1] : m_extent[1],
+ v[2] < MT_Scalar(0.0) ? -m_extent[2] : m_extent[2]);
+
+}
+
+
+bool DT_Box::ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const
+{
+ T_Outcode source_bits = outcode(source);
+ T_Outcode target_bits = outcode(target);
+
+ if ((source_bits & target_bits) == 0x0)
+ // None of the side planes separate the ray from the box.
+ {
+ MT_Scalar lambda_enter = MT_Scalar(0.0);
+ MT_Scalar lambda_exit = param;
+ MT_Vector3 r = target - source;
+ T_Outcode normal_bit = 0x0; // Indicates the axis that is returned as normal.
+ T_Outcode bit = 0x01;
+ int i;
+ for (i = 0; i != 3; ++i)
+ {
+ if (source_bits & bit)
+ // Point of intersection is entering
+ {
+ MT_Scalar lambda = (-source[i] - m_extent[i]) / r[i];
+ if (lambda_enter < lambda)
+ {
+ lambda_enter = lambda;
+ normal_bit = bit;
+ }
+ }
+ else if (target_bits & bit)
+ // Point of intersection is exiting
+ {
+ MT_Scalar lambda = (-source[i] - m_extent[i]) / r[i];
+ GEN_set_min(lambda_exit, lambda);
+ }
+ bit <<=1;
+ if (source_bits & bit)
+ // Point of intersection is entering
+ {
+ MT_Scalar lambda = (-source[i] + m_extent[i]) / r[i];
+ if (lambda_enter < lambda)
+ {
+ lambda_enter = lambda;
+ normal_bit = bit;
+ }
+ }
+ else if (target_bits & bit)
+ // Point of intersection is exiting
+ {
+ MT_Scalar lambda = (-source[i] + m_extent[i]) / r[i];
+ GEN_set_min(lambda_exit, lambda);
+ }
+ bit <<=1;
+ }
+ if (lambda_enter <= lambda_exit)
+ // The ray intersects the box
+ {
+ param = lambda_enter;
+ normal.setValue(normal_bit == 0x01 ? -MT_Scalar(1.0) :
+ normal_bit == 0x02 ? MT_Scalar(1.0) :
+ MT_Scalar(0.0),
+ normal_bit == 0x04 ? -MT_Scalar(1.0) :
+ normal_bit == 0x08 ? MT_Scalar(1.0) :
+ MT_Scalar(0.0),
+ normal_bit == 0x10 ? -MT_Scalar(1.0) :
+ normal_bit == 0x20 ? MT_Scalar(1.0) :
+ MT_Scalar(0.0));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/extern/solid/src/convex/DT_Box.h b/extern/solid/src/convex/DT_Box.h
new file mode 100644
index 00000000000..ace9634b5e3
--- /dev/null
+++ b/extern/solid/src/convex/DT_Box.h
@@ -0,0 +1,62 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_BOX_H
+#define DT_BOX_H
+
+#include "DT_Convex.h"
+
+class DT_Box : public DT_Convex {
+public:
+ DT_Box(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ m_extent(x, y, z)
+ {}
+
+ DT_Box(const MT_Vector3& e) :
+ m_extent(e)
+ {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const;
+
+ const MT_Vector3& getExtent() const { return m_extent; }
+
+protected:
+ typedef unsigned int T_Outcode;
+
+ T_Outcode outcode(const MT_Point3& p) const
+ {
+ return (p[0] < -m_extent[0] ? 0x01 : 0x0) |
+ (p[0] > m_extent[0] ? 0x02 : 0x0) |
+ (p[1] < -m_extent[1] ? 0x04 : 0x0) |
+ (p[1] > m_extent[1] ? 0x08 : 0x0) |
+ (p[2] < -m_extent[2] ? 0x10 : 0x0) |
+ (p[2] > m_extent[2] ? 0x20 : 0x0);
+ }
+
+ MT_Vector3 m_extent;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Cone.cpp b/extern/solid/src/convex/DT_Cone.cpp
new file mode 100644
index 00000000000..1dd6a7ddbbe
--- /dev/null
+++ b/extern/solid/src/convex/DT_Cone.cpp
@@ -0,0 +1,48 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Cone.h"
+
+MT_Point3 DT_Cone::support(const MT_Vector3& v) const
+{
+ MT_Scalar v_len = v.length();
+
+ if (v[1] > v_len * sinAngle)
+ {
+ return MT_Point3(MT_Scalar(0.0), halfHeight, MT_Scalar(0.0));
+ }
+ else
+ {
+ MT_Scalar s = MT_sqrt(v[0] * v[0] + v[2] * v[2]);
+ if (s != MT_Scalar(0.0))
+ {
+ MT_Scalar d = bottomRadius / s;
+ return MT_Point3(v[0] * d, -halfHeight, v[2] * d);
+ }
+ else
+ {
+ return MT_Point3(bottomRadius, -halfHeight, MT_Scalar(0.0));
+ }
+ }
+}
+
diff --git a/extern/solid/src/convex/DT_Cone.h b/extern/solid/src/convex/DT_Cone.h
new file mode 100644
index 00000000000..85e416877dd
--- /dev/null
+++ b/extern/solid/src/convex/DT_Cone.h
@@ -0,0 +1,45 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_CONE_H
+#define DT_CONE_H
+
+#include "DT_Convex.h"
+
+class DT_Cone : public DT_Convex {
+public:
+ DT_Cone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ halfHeight(h * MT_Scalar(0.5)),
+ sinAngle(r / MT_sqrt(r * r + h * h))
+ {}
+
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+protected:
+ MT_Scalar bottomRadius;
+ MT_Scalar halfHeight;
+ MT_Scalar sinAngle;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Convex.cpp b/extern/solid/src/convex/DT_Convex.cpp
new file mode 100644
index 00000000000..3be47f6ed02
--- /dev/null
+++ b/extern/solid/src/convex/DT_Convex.cpp
@@ -0,0 +1,426 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Convex.h"
+#include "GEN_MinMax.h"
+
+//#define DEBUG
+#define SAFE_EXIT
+
+#include "DT_GJK.h"
+#include "DT_PenDepth.h"
+
+#include <algorithm>
+#include <new>
+
+#include "MT_BBox.h"
+#include "DT_Sphere.h"
+#include "DT_Minkowski.h"
+
+#include "DT_Accuracy.h"
+
+#ifdef STATISTICS
+int num_iterations = 0;
+int num_irregularities = 0;
+#endif
+
+MT_BBox DT_Convex::bbox() const
+{
+ MT_Point3 min(-supportH(MT_Vector3(-1.0f, 0.0f, 0.0f)),
+ -supportH(MT_Vector3(0.0f, -1.0f, 0.0f)),
+ -supportH(MT_Vector3(0.0f, 0.0f, -1.0f)));
+ MT_Point3 max( supportH(MT_Vector3(1.0f, 0.0f, 0.0f)),
+ supportH(MT_Vector3(0.0f, 1.0f, 0.0f)),
+ supportH(MT_Vector3(0.0f, 0.0f, 1.0f)));
+
+
+ return MT_BBox(min, max);
+}
+
+MT_BBox DT_Convex::bbox(const MT_Matrix3x3& basis) const
+{
+ MT_Point3 min(-supportH(-basis[0]),
+ -supportH(-basis[1]),
+ -supportH(-basis[2]));
+ MT_Point3 max( supportH( basis[0]),
+ supportH( basis[1]),
+ supportH( basis[2]));
+ return MT_BBox(min, max);
+}
+
+MT_BBox DT_Convex::bbox(const MT_Transform& t, MT_Scalar margin) const
+{
+ MT_Point3 min(t.getOrigin()[0] - supportH(-t.getBasis()[0]) - margin,
+ t.getOrigin()[1] - supportH(-t.getBasis()[1]) - margin,
+ t.getOrigin()[2] - supportH(-t.getBasis()[2]) - margin);
+ MT_Point3 max(t.getOrigin()[0] + supportH( t.getBasis()[0]) + margin,
+ t.getOrigin()[1] + supportH( t.getBasis()[1]) + margin,
+ t.getOrigin()[2] + supportH( t.getBasis()[2]) + margin);
+ return MT_BBox(min, max);
+}
+
+bool DT_Convex::ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& lambda, MT_Vector3& normal) const
+{
+ // Still working on this one...
+ return false;
+}
+
+bool intersect(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v)
+{
+ DT_GJK gjk;
+
+#ifdef STATISTICS
+ num_iterations = 0;
+#endif
+ MT_Scalar dist2 = MT_INFINITY;
+
+ do
+ {
+ MT_Point3 p = a.support(-v);
+ MT_Point3 q = b.support(v);
+ MT_Vector3 w = p - q;
+
+ if (v.dot(w) > MT_Scalar(0.0))
+ {
+ return false;
+ }
+
+ gjk.addVertex(w);
+
+#ifdef STATISTICS
+ ++num_iterations;
+#endif
+ if (!gjk.closest(v))
+ {
+#ifdef STATISTICS
+ ++num_irregularities;
+#endif
+ return false;
+ }
+
+#ifdef SAFE_EXIT
+ MT_Scalar prev_dist2 = dist2;
+#endif
+
+ dist2 = v.length2();
+
+#ifdef SAFE_EXIT
+ if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2)
+ {
+ return false;
+ }
+#endif
+ }
+ while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex());
+
+ v.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ return true;
+}
+
+
+
+
+bool common_point(const DT_Convex& a, const DT_Convex& b,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_GJK gjk;
+
+#ifdef STATISTICS
+ num_iterations = 0;
+#endif
+
+ MT_Scalar dist2 = MT_INFINITY;
+
+ do
+ {
+ MT_Point3 p = a.support(-v);
+ MT_Point3 q = b.support(v);
+ MT_Vector3 w = p - q;
+
+ if (v.dot(w) > MT_Scalar(0.0))
+ {
+ return false;
+ }
+
+ gjk.addVertex(w, p, q);
+
+#ifdef STATISTICS
+ ++num_iterations;
+#endif
+ if (!gjk.closest(v))
+ {
+#ifdef STATISTICS
+ ++num_irregularities;
+#endif
+ return false;
+ }
+
+#ifdef SAFE_EXIT
+ MT_Scalar prev_dist2 = dist2;
+#endif
+
+ dist2 = v.length2();
+
+#ifdef SAFE_EXIT
+ if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2)
+ {
+ return false;
+ }
+#endif
+ }
+ while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex());
+
+ gjk.compute_points(pa, pb);
+
+ v.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ return true;
+}
+
+
+
+
+
+
+
+bool penetration_depth(const DT_Convex& a, const DT_Convex& b,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ DT_GJK gjk;
+
+#ifdef STATISTICS
+ num_iterations = 0;
+#endif
+
+ MT_Scalar dist2 = MT_INFINITY;
+
+ do
+ {
+ MT_Point3 p = a.support(-v);
+ MT_Point3 q = b.support(v);
+ MT_Vector3 w = p - q;
+
+ if (v.dot(w) > MT_Scalar(0.0))
+ {
+ return false;
+ }
+
+ gjk.addVertex(w, p, q);
+
+#ifdef STATISTICS
+ ++num_iterations;
+#endif
+ if (!gjk.closest(v))
+ {
+#ifdef STATISTICS
+ ++num_irregularities;
+#endif
+ return false;
+ }
+
+#ifdef SAFE_EXIT
+ MT_Scalar prev_dist2 = dist2;
+#endif
+
+ dist2 = v.length2();
+
+#ifdef SAFE_EXIT
+ if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2)
+ {
+ return false;
+ }
+#endif
+ }
+ while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex());
+
+
+ return penDepth(gjk, a, b, v, pa, pb);
+
+}
+
+bool hybrid_penetration_depth(const DT_Convex& a, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+ MT_Scalar margin = a_margin + b_margin;
+ if (margin > MT_Scalar(0.0))
+ {
+ MT_Scalar margin2 = margin * margin;
+
+ DT_GJK gjk;
+
+#ifdef STATISTICS
+ num_iterations = 0;
+#endif
+ MT_Scalar dist2 = MT_INFINITY;
+
+ do
+ {
+ MT_Point3 p = a.support(-v);
+ MT_Point3 q = b.support(v);
+
+ MT_Vector3 w = p - q;
+
+ MT_Scalar delta = v.dot(w);
+
+ if (delta > MT_Scalar(0.0) && delta * delta > dist2 * margin2)
+ {
+ return false;
+ }
+
+ if (gjk.inSimplex(w) || dist2 - delta <= dist2 * DT_Accuracy::rel_error2)
+ {
+ gjk.compute_points(pa, pb);
+ MT_Scalar s = MT_sqrt(dist2);
+ assert(s > MT_Scalar(0.0));
+ pa -= v * (a_margin / s);
+ pb += v * (b_margin / s);
+ return true;
+ }
+
+ gjk.addVertex(w, p, q);
+
+#ifdef STATISTICS
+ ++num_iterations;
+#endif
+ if (!gjk.closest(v))
+ {
+#ifdef STATISTICS
+ ++num_irregularities;
+#endif
+ gjk.compute_points(pa, pb);
+ MT_Scalar s = MT_sqrt(dist2);
+ assert(s > MT_Scalar(0.0));
+ pa -= v * (a_margin / s);
+ pb += v * (b_margin / s);
+ return true;
+ }
+
+#ifdef SAFE_EXIT
+ MT_Scalar prev_dist2 = dist2;
+#endif
+
+ dist2 = v.length2();
+
+#ifdef SAFE_EXIT
+ if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2)
+ {
+ gjk.backup_closest(v);
+ dist2 = v.length2();
+ gjk.compute_points(pa, pb);
+ MT_Scalar s = MT_sqrt(dist2);
+ assert(s > MT_Scalar(0.0));
+ pa -= v * (a_margin / s);
+ pb += v * (b_margin / s);
+ return true;
+ }
+#endif
+ }
+ while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex());
+
+ }
+ // Second GJK phase. compute points on the boundary of the offset object
+
+ return penetration_depth((a_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(a, DT_Sphere(a_margin))) :
+ static_cast<const DT_Convex&>(a)),
+ (b_margin > MT_Scalar(0.0) ?
+ static_cast<const DT_Convex&>(DT_Minkowski(b, DT_Sphere(b_margin))) :
+ static_cast<const DT_Convex&>(b)), v, pa, pb);
+}
+
+
+MT_Scalar closest_points(const DT_Convex& a, const DT_Convex& b, MT_Scalar max_dist2,
+ MT_Point3& pa, MT_Point3& pb)
+{
+ MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ DT_GJK gjk;
+
+#ifdef STATISTICS
+ num_iterations = 0;
+#endif
+
+ MT_Scalar dist2 = MT_INFINITY;
+
+ do
+ {
+ MT_Point3 p = a.support(-v);
+ MT_Point3 q = b.support(v);
+ MT_Vector3 w = p - q;
+
+ MT_Scalar delta = v.dot(w);
+ if (delta > MT_Scalar(0.0) && delta * delta > dist2 * max_dist2)
+ {
+ return MT_INFINITY;
+ }
+
+ if (gjk.inSimplex(w) || dist2 - delta <= dist2 * DT_Accuracy::rel_error2)
+ {
+ break;
+ }
+
+ gjk.addVertex(w, p, q);
+
+#ifdef STATISTICS
+ ++num_iterations;
+ if (num_iterations > 1000)
+ {
+ std::cout << "v: " << v << " w: " << w << std::endl;
+ }
+#endif
+ if (!gjk.closest(v))
+ {
+#ifdef STATISTICS
+ ++num_irregularities;
+#endif
+ break;
+ }
+
+#ifdef SAFE_EXIT
+ MT_Scalar prev_dist2 = dist2;
+#endif
+
+ dist2 = v.length2();
+
+#ifdef SAFE_EXIT
+ if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2)
+ {
+ gjk.backup_closest(v);
+ dist2 = v.length2();
+ break;
+ }
+#endif
+ }
+ while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex());
+
+ assert(!gjk.emptySimplex());
+
+ if (dist2 <= max_dist2)
+ {
+ gjk.compute_points(pa, pb);
+ }
+
+ return dist2;
+}
diff --git a/extern/solid/src/convex/DT_Convex.h b/extern/solid/src/convex/DT_Convex.h
new file mode 100644
index 00000000000..dd620ac8b98
--- /dev/null
+++ b/extern/solid/src/convex/DT_Convex.h
@@ -0,0 +1,64 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_CONVEX_H
+#define DT_CONVEX_H
+
+#include "DT_Shape.h"
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+class DT_Convex : public DT_Shape {
+public:
+ virtual ~DT_Convex() {}
+ virtual DT_ShapeType getType() const { return CONVEX; }
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const { return v.dot(support(v)); }
+ virtual MT_Point3 support(const MT_Vector3& v) const = 0;
+ virtual MT_BBox bbox() const;
+ virtual MT_BBox bbox(const MT_Matrix3x3& basis) const;
+ virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin = MT_Scalar(0.0)) const;
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& param, MT_Vector3& normal) const;
+
+protected:
+ DT_Convex() {}
+};
+
+
+bool intersect(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v);
+
+bool common_point(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+MT_Scalar closest_points(const DT_Convex&, const DT_Convex&, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb);
+
+bool penetration_depth(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+bool hybrid_penetration_depth(const DT_Convex& a, MT_Scalar a_margin,
+ const DT_Convex& b, MT_Scalar b_margin,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+#endif
diff --git a/extern/solid/src/convex/DT_Cylinder.cpp b/extern/solid/src/convex/DT_Cylinder.cpp
new file mode 100644
index 00000000000..cff5ebcefb1
--- /dev/null
+++ b/extern/solid/src/convex/DT_Cylinder.cpp
@@ -0,0 +1,39 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Cylinder.h"
+
+MT_Point3 DT_Cylinder::support(const MT_Vector3& v) const
+{
+ MT_Scalar s = MT_sqrt(v[0] * v[0] + v[2] * v[2]);
+ if (s != MT_Scalar(0.0))
+ {
+ MT_Scalar d = radius / s;
+ return MT_Point3(v[0] * d, v[1] < 0.0 ? -halfHeight : halfHeight, v[2] * d);
+ }
+ else
+ {
+ return MT_Point3(radius, v[1] < 0.0 ? -halfHeight : halfHeight, MT_Scalar(0.0));
+ }
+}
+
diff --git a/extern/solid/src/convex/DT_Cylinder.h b/extern/solid/src/convex/DT_Cylinder.h
new file mode 100644
index 00000000000..2a0c07fd579
--- /dev/null
+++ b/extern/solid/src/convex/DT_Cylinder.h
@@ -0,0 +1,42 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_CYLINDER_H
+#define DT_CYLINDER_H
+
+#include "DT_Convex.h"
+
+class DT_Cylinder : public DT_Convex {
+public:
+ DT_Cylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ halfHeight(h * MT_Scalar(0.5)) {}
+
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+protected:
+ MT_Scalar radius;
+ MT_Scalar halfHeight;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Facet.cpp b/extern/solid/src/convex/DT_Facet.cpp
new file mode 100644
index 00000000000..87ae5c3e0be
--- /dev/null
+++ b/extern/solid/src/convex/DT_Facet.cpp
@@ -0,0 +1,80 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Facet.h"
+
+bool DT_Facet::link(int edge0, DT_Facet *facet, int edge1)
+{
+ m_adjFacets[edge0] = facet;
+ m_adjEdges[edge0] = edge1;
+ facet->m_adjFacets[edge1] = this;
+ facet->m_adjEdges[edge1] = edge0;
+
+ bool b = m_indices[edge0] == facet->m_indices[incMod3(edge1)] &&
+ m_indices[incMod3(edge0)] == facet->m_indices[edge1];
+ return b;
+}
+
+bool DT_Facet::computeClosest(const MT_Vector3 *verts)
+{
+ const MT_Vector3& p0 = verts[m_indices[0]];
+
+ MT_Vector3 v1 = verts[m_indices[1]] - p0;
+ MT_Vector3 v2 = verts[m_indices[2]] - p0;
+ MT_Scalar v1dv1 = v1.length2();
+ MT_Scalar v1dv2 = v1.dot(v2);
+ MT_Scalar v2dv2 = v2.length2();
+ MT_Scalar p0dv1 = p0.dot(v1);
+ MT_Scalar p0dv2 = p0.dot(v2);
+
+ m_det = v1dv1 * v2dv2 - v1dv2 * v1dv2; // non-negative
+ m_lambda1 = p0dv2 * v1dv2 - p0dv1 * v2dv2;
+ m_lambda2 = p0dv1 * v1dv2 - p0dv2 * v1dv1;
+
+ if (m_det > MT_Scalar(0.0)) {
+ m_closest = p0 + (m_lambda1 * v1 + m_lambda2 * v2) / m_det;
+ m_dist2 = m_closest.length2();
+ return true;
+ }
+
+ return false;
+}
+
+void DT_Facet::silhouette(int index, const MT_Vector3& w,
+ DT_EdgeBuffer& edgeBuffer)
+{
+ if (!m_obsolete) {
+ if (m_closest.dot(w) < m_dist2) {
+ edgeBuffer.push_back(DT_Edge(this, index));
+ }
+ else {
+ m_obsolete = true; // Facet is visible
+ int next = incMod3(index);
+ m_adjFacets[next]->silhouette(m_adjEdges[next], w, edgeBuffer);
+ next = incMod3(next);
+ m_adjFacets[next]->silhouette(m_adjEdges[next], w, edgeBuffer);
+ }
+ }
+}
+
+
diff --git a/extern/solid/src/convex/DT_Facet.h b/extern/solid/src/convex/DT_Facet.h
new file mode 100644
index 00000000000..873706346b8
--- /dev/null
+++ b/extern/solid/src/convex/DT_Facet.h
@@ -0,0 +1,134 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_FACET_H
+#define DT_FACET_H
+
+#include <string.h>
+#include <vector>
+
+#include <MT_Vector3.h>
+#include <MT_Point3.h>
+
+class DT_Facet;
+
+
+class DT_Edge {
+public:
+ DT_Edge() {}
+ DT_Edge(DT_Facet *facet, int index) :
+ m_facet(facet),
+ m_index(index) {}
+
+ DT_Facet *getFacet() const { return m_facet; }
+ int getIndex() const { return m_index; }
+
+ int getSource() const;
+ int getTarget() const;
+
+private:
+ DT_Facet *m_facet;
+ int m_index;
+};
+
+typedef std::vector<DT_Edge> DT_EdgeBuffer;
+
+
+class DT_Facet {
+public:
+ DT_Facet() {}
+ DT_Facet(int i0, int i1, int i2)
+ : m_obsolete(false)
+ {
+ m_indices[0] = i0;
+ m_indices[1] = i1;
+ m_indices[2] = i2;
+ }
+
+ int operator[](int i) const { return m_indices[i]; }
+
+ bool link(int edge0, DT_Facet *facet, int edge1);
+
+
+ bool isObsolete() const { return m_obsolete; }
+
+
+ bool computeClosest(const MT_Vector3 *verts);
+
+ const MT_Vector3& getClosest() const { return m_closest; }
+
+ bool isClosestInternal() const
+ {
+ return m_lambda1 >= MT_Scalar(0.0) &&
+ m_lambda2 >= MT_Scalar(0.0) &&
+ m_lambda1 + m_lambda2 <= m_det;
+ }
+
+ MT_Scalar getDist2() const { return m_dist2; }
+
+ MT_Point3 getClosestPoint(const MT_Point3 *points) const
+ {
+ const MT_Point3& p0 = points[m_indices[0]];
+
+ return p0 + (m_lambda1 * (points[m_indices[1]] - p0) +
+ m_lambda2 * (points[m_indices[2]] - p0)) / m_det;
+ }
+
+ void silhouette(const MT_Vector3& w, DT_EdgeBuffer& edgeBuffer)
+ {
+ edgeBuffer.clear();
+ m_obsolete = true;
+ m_adjFacets[0]->silhouette(m_adjEdges[0], w, edgeBuffer);
+ m_adjFacets[1]->silhouette(m_adjEdges[1], w, edgeBuffer);
+ m_adjFacets[2]->silhouette(m_adjEdges[2], w, edgeBuffer);
+ }
+
+private:
+ void silhouette(int index, const MT_Vector3& w, DT_EdgeBuffer& edgeBuffer);
+
+ int m_indices[3];
+ bool m_obsolete;
+ DT_Facet *m_adjFacets[3];
+ int m_adjEdges[3];
+
+ MT_Scalar m_det;
+ MT_Scalar m_lambda1;
+ MT_Scalar m_lambda2;
+ MT_Vector3 m_closest;
+ MT_Scalar m_dist2;
+};
+
+
+inline int incMod3(int i) { return ++i % 3; }
+
+inline int DT_Edge::getSource() const
+{
+ return (*m_facet)[m_index];
+}
+
+inline int DT_Edge::getTarget() const
+{
+ return (*m_facet)[incMod3(m_index)];
+}
+
+#endif
diff --git a/extern/solid/src/convex/DT_GJK.h b/extern/solid/src/convex/DT_GJK.h
new file mode 100644
index 00000000000..d8f44acf85e
--- /dev/null
+++ b/extern/solid/src/convex/DT_GJK.h
@@ -0,0 +1,438 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_GJK_H
+#define DT_GJK_H
+
+//#define USE_BACKUP_PROCEDURE
+#define JOHNSON_ROBUST
+#define FAST_CLOSEST
+
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "GEN_MinMax.h"
+#include "DT_Accuracy.h"
+
+
+class DT_GJK {
+private:
+ typedef unsigned int T_Bits;
+ inline static bool subseteq(T_Bits a, T_Bits b) { return (a & b) == a; }
+ inline static bool contains(T_Bits a, T_Bits b) { return (a & b) != 0x0; }
+
+public:
+ DT_GJK() :
+ m_bits(0x0),
+ m_all_bits(0x0)
+ {}
+
+ bool emptySimplex() const { return m_bits == 0x0; }
+ bool fullSimplex() const { return m_bits == 0xf; }
+
+ void reset()
+ {
+ m_bits = 0x0;
+ m_all_bits = 0x0;
+ }
+
+ bool inSimplex(const MT_Vector3& w)
+ {
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(m_all_bits, bit) && w == m_y[i])
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void addVertex(const MT_Vector3& w)
+ {
+ assert(!fullSimplex());
+ m_last = 0;
+ m_last_bit = 0x1;
+ while (contains(m_bits, m_last_bit))
+ {
+ ++m_last;
+ m_last_bit <<= 1;
+ }
+ m_y[m_last] = w;
+ m_ylen2[m_last] = w.length2();
+ m_all_bits = m_bits | m_last_bit;
+
+ update_cache();
+ compute_det();
+ }
+
+ void addVertex(const MT_Vector3& w, const MT_Point3& p, const MT_Point3& q)
+ {
+ addVertex(w);
+ m_p[m_last] = p;
+ m_q[m_last] = q;
+ }
+
+ int getSimplex(MT_Point3 *pBuf, MT_Point3 *qBuf, MT_Vector3 *yBuf) const
+ {
+ int num_verts = 0;
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(m_bits, bit))
+ {
+ pBuf[num_verts] = m_p[i];
+ qBuf[num_verts] = m_q[i];
+ yBuf[num_verts] = m_y[i];
+
+#ifdef DEBUG
+ std::cout << "Point " << i << " = " << m_y[i] << std::endl;
+#endif
+
+ ++num_verts;
+ }
+ }
+ return num_verts;
+ }
+
+ void compute_points(MT_Point3& p1, MT_Point3& p2)
+ {
+ MT_Scalar sum = MT_Scalar(0.0);
+ p1.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+ p2.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(m_bits, bit))
+ {
+ sum += m_det[m_bits][i];
+ p1 += m_p[i] * m_det[m_bits][i];
+ p2 += m_q[i] * m_det[m_bits][i];
+ }
+ }
+
+ assert(sum > MT_Scalar(0.0));
+ MT_Scalar s = MT_Scalar(1.0) / sum;
+ p1 *= s;
+ p2 *= s;
+ }
+
+ bool closest(MT_Vector3& v)
+ {
+#ifdef FAST_CLOSEST
+ T_Bits s;
+ for (s = m_bits; s != 0x0; --s)
+ {
+ if (subseteq(s, m_bits) && valid(s | m_last_bit))
+ {
+ m_bits = s | m_last_bit;
+ compute_vector(m_bits, v);
+ return true;
+ }
+ }
+ if (valid(m_last_bit))
+ {
+ m_bits = m_last_bit;
+ m_maxlen2 = m_ylen2[m_last];
+ v = m_y[m_last];
+ return true;
+ }
+#else
+ T_Bits s;
+ for (s = m_all_bits; s != 0x0; --s)
+ {
+ if (subseteq(s, m_all_bits) && valid(s))
+ {
+ m_bits = s;
+ compute_vector(m_bits, v);
+ return true;
+ }
+ }
+#endif
+
+ // Original GJK calls the backup procedure at this point.
+#ifdef USE_BACKUP_PROCEDURE
+ backup_closest(MT_Vector3& v);
+#endif
+ return false;
+ }
+
+ void backup_closest(MT_Vector3& v)
+ {
+ MT_Scalar min_dist2 = MT_INFINITY;
+
+ T_Bits s;
+ for (s = m_all_bits; s != 0x0; --s)
+ {
+ if (subseteq(s, m_all_bits) && proper(s))
+ {
+ MT_Vector3 u;
+ compute_vector(s, u);
+ MT_Scalar dist2 = u.length2();
+ if (dist2 < min_dist2)
+ {
+ min_dist2 = dist2;
+ m_bits = s;
+ v = u;
+ }
+ }
+ }
+ }
+
+ MT_Scalar maxVertex() { return m_maxlen2; }
+
+
+private:
+ void update_cache();
+ void compute_det();
+
+ bool valid(T_Bits s)
+ {
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(m_all_bits, bit))
+ {
+ if (contains(s, bit))
+ {
+ if (m_det[s][i] <= MT_Scalar(0.0))
+ {
+ return false;
+ }
+ }
+ else if (m_det[s | bit][i] > MT_Scalar(0.0))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ bool proper(T_Bits s)
+ {
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(s, bit) && m_det[s][i] <= MT_Scalar(0.0))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void compute_vector(T_Bits s, MT_Vector3& v)
+ {
+ m_maxlen2 = MT_Scalar(0.0);
+ MT_Scalar sum = MT_Scalar(0.0);
+ v .setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(s, bit))
+ {
+ sum += m_det[s][i];
+ GEN_set_max(m_maxlen2, m_ylen2[i]);
+ v += m_y[i] * m_det[s][i];
+ }
+ }
+
+ assert(sum > MT_Scalar(0.0));
+
+ v /= sum;
+ }
+
+private:
+ MT_Scalar m_det[16][4]; // cached sub-determinants
+ MT_Vector3 m_edge[4][4];
+
+#ifdef JOHNSON_ROBUST
+ MT_Scalar m_norm[4][4];
+#endif
+
+ MT_Point3 m_p[4]; // support points of object A in local coordinates
+ MT_Point3 m_q[4]; // support points of object B in local coordinates
+ MT_Vector3 m_y[4]; // support points of A - B in world coordinates
+ MT_Scalar m_ylen2[4]; // Squared lengths support points y
+
+ MT_Scalar m_maxlen2; // Maximum squared length to a vertex of the current
+ // simplex
+ T_Bits m_bits; // identifies current simplex
+ T_Bits m_last; // identifies last found support point
+ T_Bits m_last_bit; // m_last_bit == 0x1 << last
+ T_Bits m_all_bits; // m_all_bits == m_bits | m_last_bit
+};
+
+
+
+
+inline void DT_GJK::update_cache()
+{
+ int i;
+ T_Bits bit;
+ for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
+ {
+ if (contains(m_bits, bit))
+ {
+ m_edge[i][m_last] = m_y[i] - m_y[m_last];
+ m_edge[m_last][i] = -m_edge[i][m_last];
+
+#ifdef JOHNSON_ROBUST
+ m_norm[i][m_last] = m_norm[m_last][i] = m_edge[i][m_last].length2();
+#endif
+
+ }
+ }
+}
+
+#ifdef JOHNSON_ROBUST
+
+inline void DT_GJK::compute_det()
+{
+ m_det[m_last_bit][m_last] = 1;
+
+ int i;
+ T_Bits si;
+ for (i = 0, si = 0x1; i < 4; ++i, si <<= 1)
+ {
+ if (contains(m_bits, si))
+ {
+ T_Bits s2 = si | m_last_bit;
+ m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]);
+ m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
+
+ int j;
+ T_Bits sj;
+ for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1)
+ {
+ if (contains(m_bits, sj))
+ {
+ int k;
+ T_Bits s3 = sj | s2;
+
+ k = m_norm[i][j] < m_norm[m_last][j] ? i : m_last;
+ m_det[s3][j] = m_det[s2][i] * m_edge[k][j].dot(m_y[i]) +
+ m_det[s2][m_last] * m_edge[k][j].dot(m_y[m_last]);
+ k = m_norm[j][i] < m_norm[m_last][i] ? j : m_last;
+ m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[k][i].dot(m_y[j]) +
+ m_det[sj|m_last_bit][m_last] * m_edge[k][i].dot(m_y[m_last]);
+ k = m_norm[i][m_last] < m_norm[j][m_last] ? i : j;
+ m_det[s3][m_last] = m_det[sj|si][j] * m_edge[k][m_last].dot(m_y[j]) +
+ m_det[sj|si][i] * m_edge[k][m_last].dot(m_y[i]);
+ }
+ }
+ }
+ }
+
+ if (m_all_bits == 0xf)
+ {
+ int k;
+
+ k = m_norm[1][0] < m_norm[2][0] ? (m_norm[1][0] < m_norm[3][0] ? 1 : 3) : (m_norm[2][0] < m_norm[3][0] ? 2 : 3);
+
+ m_det[0xf][0] = m_det[0xe][1] * m_edge[k][0].dot(m_y[1]) +
+ m_det[0xe][2] * m_edge[k][0].dot(m_y[2]) +
+ m_det[0xe][3] * m_edge[k][0].dot(m_y[3]);
+
+ k = m_norm[0][1] < m_norm[2][1] ? (m_norm[0][1] < m_norm[3][1] ? 0 : 3) : (m_norm[2][1] < m_norm[3][1] ? 2 : 3);
+
+ m_det[0xf][1] = m_det[0xd][0] * m_edge[k][1].dot(m_y[0]) +
+ m_det[0xd][2] * m_edge[k][1].dot(m_y[2]) +
+ m_det[0xd][3] * m_edge[k][1].dot(m_y[3]);
+
+ k = m_norm[0][2] < m_norm[1][2] ? (m_norm[0][2] < m_norm[3][2] ? 0 : 3) : (m_norm[1][2] < m_norm[3][2] ? 1 : 3);
+
+ m_det[0xf][2] = m_det[0xb][0] * m_edge[k][2].dot(m_y[0]) +
+ m_det[0xb][1] * m_edge[k][2].dot(m_y[1]) +
+ m_det[0xb][3] * m_edge[k][2].dot(m_y[3]);
+
+ k = m_norm[0][3] < m_norm[1][3] ? (m_norm[0][3] < m_norm[2][3] ? 0 : 2) : (m_norm[1][3] < m_norm[2][3] ? 1 : 2);
+
+ m_det[0xf][3] = m_det[0x7][0] * m_edge[k][3].dot(m_y[0]) +
+ m_det[0x7][1] * m_edge[k][3].dot(m_y[1]) +
+ m_det[0x7][2] * m_edge[k][3].dot(m_y[2]);
+ }
+}
+
+#else
+
+inline void DT_GJK::compute_det()
+{
+ m_det[m_last_bit][m_last] = 1;
+
+ int i;
+ T_Bits si;
+ for (i = 0, si = 0x1; i < 4; ++i, si <<= 1)
+ {
+ if (contains(m_bits, si))
+ {
+ T_Bits s2 = si | m_last_bit;
+ m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]);
+ m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
+
+ int j;
+ T_Bits sj;
+ for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1)
+ {
+ if (contains(m_bits, sj))
+ {
+ T_Bits s3 = sj | s2;
+ m_det[s3][j] = m_det[s2][i] * m_edge[i][j].dot(m_y[i]) +
+ m_det[s2][m_last] * m_edge[i][j].dot(m_y[m_last]);
+ m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[j][i].dot(m_y[j]) +
+ m_det[sj|m_last_bit][m_last] * m_edge[j][i].dot(m_y[m_last]);
+ m_det[s3][m_last] = m_det[sj|si][j] * m_edge[j][m_last].dot(m_y[j]) +
+ m_det[sj|si][i] * m_edge[j][m_last].dot(m_y[i]);
+ }
+ }
+ }
+ }
+
+ if (m_all_bits == 0xf)
+ {
+ m_det[0xf][0] = m_det[0xe][1] * m_edge[1][0].dot(m_y[1]) +
+ m_det[0xe][2] * m_edge[1][0].dot(m_y[2]) +
+ m_det[0xe][3] * m_edge[1][0].dot(m_y[3]);
+ m_det[0xf][1] = m_det[0xd][0] * m_edge[0][1].dot(m_y[0]) +
+ m_det[0xd][2] * m_edge[0][1].dot(m_y[2]) +
+ m_det[0xd][3] * m_edge[0][1].dot(m_y[3]);
+ m_det[0xf][2] = m_det[0xb][0] * m_edge[0][2].dot(m_y[0]) +
+ m_det[0xb][1] * m_edge[0][2].dot(m_y[1]) +
+ m_det[0xb][3] * m_edge[0][2].dot(m_y[3]);
+ m_det[0xf][3] = m_det[0x7][0] * m_edge[0][3].dot(m_y[0]) +
+ m_det[0x7][1] * m_edge[0][3].dot(m_y[1]) +
+ m_det[0x7][2] * m_edge[0][3].dot(m_y[2]);
+ }
+}
+
+#endif
+
+#endif
diff --git a/extern/solid/src/convex/DT_Hull.h b/extern/solid/src/convex/DT_Hull.h
new file mode 100644
index 00000000000..a5bf56ae59d
--- /dev/null
+++ b/extern/solid/src/convex/DT_Hull.h
@@ -0,0 +1,53 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_HULL_H
+#define DT_HULL_H
+
+#include "DT_Convex.h"
+
+class DT_Hull : public DT_Convex {
+public:
+ DT_Hull(const DT_Convex& lchild, const DT_Convex& rchild) :
+ m_lchild(lchild),
+ m_rchild(rchild)
+ {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const
+ {
+ return GEN_max(m_lchild.supportH(v), m_rchild.supportH(v));
+ }
+
+ virtual MT_Point3 support(const MT_Vector3& v) const
+ {
+ MT_Point3 lpnt = m_lchild.support(v);
+ MT_Point3 rpnt = m_rchild.support(v);
+ return v.dot(lpnt) > v.dot(rpnt) ? lpnt : rpnt;
+ }
+
+private:
+ const DT_Convex& m_lchild;
+ const DT_Convex& m_rchild;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_IndexArray.h b/extern/solid/src/convex/DT_IndexArray.h
new file mode 100644
index 00000000000..95551fa8483
--- /dev/null
+++ b/extern/solid/src/convex/DT_IndexArray.h
@@ -0,0 +1,33 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_INDEXARRAY_H
+#define DT_INDEXARRAY_H
+
+#include "SOLID_types.h"
+#include "DT_Array.h"
+
+typedef DT_Array<DT_Index, DT_Count> DT_IndexArray;
+
+#endif
+
diff --git a/extern/solid/src/convex/DT_LineSegment.cpp b/extern/solid/src/convex/DT_LineSegment.cpp
new file mode 100644
index 00000000000..6c7ccf6b9b7
--- /dev/null
+++ b/extern/solid/src/convex/DT_LineSegment.cpp
@@ -0,0 +1,36 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_LineSegment.h"
+
+MT_Scalar DT_LineSegment::supportH(const MT_Vector3& v) const
+{
+ return GEN_max(v.dot(m_source), v.dot(m_target));
+}
+
+MT_Point3 DT_LineSegment::support(const MT_Vector3& v) const
+{
+ return v.dot(m_source) > v.dot(m_target) ? m_source : m_target;
+}
+
+
diff --git a/extern/solid/src/convex/DT_LineSegment.h b/extern/solid/src/convex/DT_LineSegment.h
new file mode 100644
index 00000000000..979ff8a18a9
--- /dev/null
+++ b/extern/solid/src/convex/DT_LineSegment.h
@@ -0,0 +1,52 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_LINESEGMENT_H
+#define DT_LINESEGMENT_H
+
+#include "DT_Convex.h"
+
+class DT_LineSegment : public DT_Convex {
+public:
+ DT_LineSegment(const MT_Point3& source, const MT_Point3& target) :
+ m_source(source),
+ m_target(target) {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+ const MT_Point3& getSource() const { return m_source; }
+ const MT_Point3& getTarget() const { return m_target; }
+
+private:
+ MT_Point3 m_source;
+ MT_Point3 m_target;
+};
+
+#endif
+
+
+
+
+
+
diff --git a/extern/solid/src/convex/DT_Minkowski.h b/extern/solid/src/convex/DT_Minkowski.h
new file mode 100644
index 00000000000..e90fed6a8e0
--- /dev/null
+++ b/extern/solid/src/convex/DT_Minkowski.h
@@ -0,0 +1,51 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_MINKOWSKI_H
+#define DT_MINKOWSKI_H
+
+#include "DT_Convex.h"
+
+class DT_Minkowski : public DT_Convex {
+public:
+ DT_Minkowski(const DT_Convex& lchild, const DT_Convex& rchild)
+ : m_lchild(lchild),
+ m_rchild(rchild)
+ {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const
+ {
+ return m_lchild.supportH(v) + m_rchild.supportH(v);
+ }
+
+ virtual MT_Point3 support(const MT_Vector3& v) const
+ {
+ return m_lchild.support(v) + (MT_Vector3)m_rchild.support(v);
+ }
+
+private:
+ const DT_Convex& m_lchild;
+ const DT_Convex& m_rchild;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_PenDepth.cpp b/extern/solid/src/convex/DT_PenDepth.cpp
new file mode 100644
index 00000000000..e1c5c9a3949
--- /dev/null
+++ b/extern/solid/src/convex/DT_PenDepth.cpp
@@ -0,0 +1,376 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_PenDepth.h"
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+#include "MT_Quaternion.h"
+#include "DT_Convex.h"
+#include "DT_GJK.h"
+#include "DT_Facet.h"
+
+//#define DEBUG
+
+const int MaxSupportPoints = 1000;
+const int MaxFacets = 2000;
+
+static MT_Point3 pBuf[MaxSupportPoints];
+static MT_Point3 qBuf[MaxSupportPoints];
+static MT_Vector3 yBuf[MaxSupportPoints];
+
+static DT_Facet facetBuf[MaxFacets];
+static int freeFacet = 0;
+static DT_Facet *facetHeap[MaxFacets];
+static int num_facets;
+
+class DT_FacetComp {
+public:
+
+ bool operator()(const DT_Facet *face1, const DT_Facet *face2)
+ {
+ return face1->getDist2() > face2->getDist2();
+ }
+
+} facetComp;
+
+inline DT_Facet *addFacet(int i0, int i1, int i2,
+ MT_Scalar lower2, MT_Scalar upper2)
+{
+ assert(i0 != i1 && i0 != i2 && i1 != i2);
+ if (freeFacet < MaxFacets)
+ {
+ DT_Facet *facet = new(&facetBuf[freeFacet++]) DT_Facet(i0, i1, i2);
+#ifdef DEBUG
+ std::cout << "Facet " << i0 << ' ' << i1 << ' ' << i2;
+#endif
+ if (facet->computeClosest(yBuf))
+ {
+ if (facet->isClosestInternal() &&
+ lower2 <= facet->getDist2() && facet->getDist2() <= upper2)
+ {
+ facetHeap[num_facets++] = facet;
+ std::push_heap(&facetHeap[0], &facetHeap[num_facets], facetComp);
+#ifdef DEBUG
+ std::cout << " accepted" << std::endl;
+#endif
+ }
+ else
+ {
+#ifdef DEBUG
+ std::cout << " rejected, ";
+ if (!facet->isClosestInternal())
+ {
+ std::cout << "closest point not internal";
+ }
+ else if (lower2 > facet->getDist2())
+ {
+ std::cout << "facet is closer than orignal facet";
+ }
+ else
+ {
+ std::cout << "facet is further than upper bound";
+ }
+ std::cout << std::endl;
+#endif
+ }
+
+ return facet;
+ }
+ }
+
+ return 0;
+}
+
+inline bool originInTetrahedron(const MT_Vector3& p1, const MT_Vector3& p2,
+ const MT_Vector3& p3, const MT_Vector3& p4)
+{
+ MT_Vector3 normal1 = (p2 - p1).cross(p3 - p1);
+ MT_Vector3 normal2 = (p3 - p2).cross(p4 - p2);
+ MT_Vector3 normal3 = (p4 - p3).cross(p1 - p3);
+ MT_Vector3 normal4 = (p1 - p4).cross(p2 - p4);
+
+ return
+ normal1.dot(p1) > MT_Scalar(0.0) != normal1.dot(p4) > MT_Scalar(0.0) &&
+ normal2.dot(p2) > MT_Scalar(0.0) != normal2.dot(p1) > MT_Scalar(0.0) &&
+ normal3.dot(p3) > MT_Scalar(0.0) != normal3.dot(p2) > MT_Scalar(0.0) &&
+ normal4.dot(p4) > MT_Scalar(0.0) != normal4.dot(p3) > MT_Scalar(0.0);
+}
+
+
+bool penDepth(const DT_GJK& gjk, const DT_Convex& a, const DT_Convex& b,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
+{
+
+ int num_verts = gjk.getSimplex(pBuf, qBuf, yBuf);
+
+ switch (num_verts)
+ {
+ case 1:
+ // Touching contact. Yes, we have a collision,
+ // but no penetration.
+ return false;
+ case 2:
+ {
+ // We have a line segment inside the Minkowski sum containing the
+ // origin. Blow it up by adding three additional support points.
+
+ MT_Vector3 dir = (yBuf[1] - yBuf[0]).normalized();
+ int axis = dir.furthestAxis();
+
+ static MT_Scalar sin_60 = MT_sqrt(MT_Scalar(3.0)) * MT_Scalar(0.5);
+
+ MT_Quaternion rot(dir[0] * sin_60, dir[1] * sin_60, dir[2] * sin_60, MT_Scalar(0.5));
+ MT_Matrix3x3 rot_mat(rot);
+
+ MT_Vector3 aux1 = dir.cross(MT_Vector3(axis == 0, axis == 1, axis == 2));
+ MT_Vector3 aux2 = rot_mat * aux1;
+ MT_Vector3 aux3 = rot_mat * aux2;
+
+ pBuf[2] = a.support(aux1);
+ qBuf[2] = b.support(-aux1);
+ yBuf[2] = pBuf[2] - qBuf[2];
+
+ pBuf[3] = a.support(aux2);
+ qBuf[3] = b.support(-aux2);
+ yBuf[3] = pBuf[3] - qBuf[3];
+
+ pBuf[4] = a.support(aux3);
+ qBuf[4] = b.support(-aux3);
+ yBuf[4] = pBuf[4] - qBuf[4];
+
+ if (originInTetrahedron(yBuf[0], yBuf[2], yBuf[3], yBuf[4]))
+ {
+ pBuf[1] = pBuf[4];
+ qBuf[1] = qBuf[4];
+ yBuf[1] = yBuf[4];
+ }
+ else if (originInTetrahedron(yBuf[1], yBuf[2], yBuf[3], yBuf[4]))
+ {
+ pBuf[0] = pBuf[4];
+ qBuf[0] = qBuf[4];
+ yBuf[0] = yBuf[4];
+ }
+ else
+ {
+ // Origin not in initial polytope
+ return false;
+ }
+
+ num_verts = 4;
+
+ break;
+ }
+ case 3:
+ {
+ // We have a triangle inside the Minkowski sum containing
+ // the origin. First blow it up.
+
+ MT_Vector3 v1 = yBuf[1] - yBuf[0];
+ MT_Vector3 v2 = yBuf[2] - yBuf[0];
+ MT_Vector3 vv = v1.cross(v2);
+
+ pBuf[3] = a.support(vv);
+ qBuf[3] = b.support(-vv);
+ yBuf[3] = pBuf[3] - qBuf[3];
+ pBuf[4] = a.support(-vv);
+ qBuf[4] = b.support(vv);
+ yBuf[4] = pBuf[4] - qBuf[4];
+
+
+ if (originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[4]))
+ {
+ pBuf[3] = pBuf[4];
+ qBuf[3] = qBuf[4];
+ yBuf[3] = yBuf[4];
+ }
+ else if (!originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[3]))
+ {
+ // Origin not in initial polytope
+ return false;
+ }
+
+ num_verts = 4;
+
+ break;
+ }
+ }
+
+ // We have a tetrahedron inside the Minkowski sum containing
+ // the origin (if GJK did it's job right ;-)
+
+
+ if (!originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[3]))
+ {
+ // assert(false);
+ return false;
+ }
+
+ num_facets = 0;
+ freeFacet = 0;
+
+ DT_Facet *f0 = addFacet(0, 1, 2, MT_Scalar(0.0), MT_INFINITY);
+ DT_Facet *f1 = addFacet(0, 3, 1, MT_Scalar(0.0), MT_INFINITY);
+ DT_Facet *f2 = addFacet(0, 2, 3, MT_Scalar(0.0), MT_INFINITY);
+ DT_Facet *f3 = addFacet(1, 3, 2, MT_Scalar(0.0), MT_INFINITY);
+
+ if (!f0 || f0->getDist2() == MT_Scalar(0.0) ||
+ !f1 || f1->getDist2() == MT_Scalar(0.0) ||
+ !f2 || f2->getDist2() == MT_Scalar(0.0) ||
+ !f3 || f3->getDist2() == MT_Scalar(0.0))
+ {
+ return false;
+ }
+
+ f0->link(0, f1, 2);
+ f0->link(1, f3, 2);
+ f0->link(2, f2, 0);
+ f1->link(0, f2, 2);
+ f1->link(1, f3, 0);
+ f2->link(1, f3, 1);
+
+ if (num_facets == 0)
+ {
+ return false;
+ }
+
+ // at least one facet on the heap.
+
+ DT_EdgeBuffer edgeBuffer(20);
+
+ DT_Facet *facet = 0;
+
+ MT_Scalar upper_bound2 = MT_INFINITY;
+
+ do {
+ facet = facetHeap[0];
+ std::pop_heap(&facetHeap[0], &facetHeap[num_facets], facetComp);
+ --num_facets;
+
+ if (!facet->isObsolete())
+ {
+ assert(facet->getDist2() > MT_Scalar(0.0));
+
+ if (num_verts == MaxSupportPoints)
+ {
+#ifdef DEBUG
+ std::cout << "Ouch, no convergence!!!" << std::endl;
+#endif
+ assert(false);
+ break;
+ }
+
+ pBuf[num_verts] = a.support(facet->getClosest());
+ qBuf[num_verts] = b.support(-facet->getClosest());
+ yBuf[num_verts] = pBuf[num_verts] - qBuf[num_verts];
+
+ int index = num_verts++;
+ MT_Scalar far_dist2 = yBuf[index].dot(facet->getClosest());
+
+ // Make sure the support mapping is OK.
+ assert(far_dist2 > MT_Scalar(0.0));
+
+ GEN_set_min(upper_bound2, far_dist2 * far_dist2 / facet->getDist2());
+
+ if (upper_bound2 <= DT_Accuracy::depth_tolerance * facet->getDist2()
+#define CHECK_NEW_SUPPORT
+#ifdef CHECK_NEW_SUPPORT
+ || yBuf[index] == yBuf[(*facet)[0]]
+ || yBuf[index] == yBuf[(*facet)[1]]
+ || yBuf[index] == yBuf[(*facet)[2]]
+#endif
+ )
+ {
+ break;
+ }
+
+ // Compute the silhouette cast by the new vertex
+ // Note that the new vertex is on the positive side
+ // of the current facet, so the current facet is will
+ // not be in the convex hull. Start local search
+ // from this facet.
+
+ facet->silhouette(yBuf[index], edgeBuffer);
+
+ if (edgeBuffer.empty())
+ {
+ return false;
+ }
+
+ DT_EdgeBuffer::const_iterator it = edgeBuffer.begin();
+ DT_Facet *firstFacet =
+ addFacet((*it).getTarget(), (*it).getSource(),
+ index, facet->getDist2(), upper_bound2);
+
+ if (!firstFacet)
+ {
+ break;
+ }
+
+ firstFacet->link(0, (*it).getFacet(), (*it).getIndex());
+ DT_Facet *lastFacet = firstFacet;
+
+ ++it;
+ for (; it != edgeBuffer.end(); ++it)
+ {
+ DT_Facet *newFacet =
+ addFacet((*it).getTarget(), (*it).getSource(),
+ index, facet->getDist2(), upper_bound2);
+
+ if (!newFacet)
+ {
+ break;
+ }
+
+ if (!newFacet->link(0, (*it).getFacet(), (*it).getIndex()))
+ {
+ break;
+ }
+
+ if (!newFacet->link(2, lastFacet, 1))
+ {
+ break;
+ }
+
+ lastFacet = newFacet;
+ }
+ if (it != edgeBuffer.end())
+ {
+ break;
+ }
+
+ firstFacet->link(2, lastFacet, 1);
+ }
+ }
+ while (num_facets > 0 && facetHeap[0]->getDist2() <= upper_bound2);
+
+#ifdef DEBUG
+ std::cout << "#facets left = " << num_facets << std::endl;
+#endif
+
+ v = facet->getClosest();
+ pa = facet->getClosestPoint(pBuf);
+ pb = facet->getClosestPoint(qBuf);
+ return true;
+}
+
diff --git a/extern/solid/src/convex/DT_PenDepth.h b/extern/solid/src/convex/DT_PenDepth.h
new file mode 100644
index 00000000000..97b3c6c0e0e
--- /dev/null
+++ b/extern/solid/src/convex/DT_PenDepth.h
@@ -0,0 +1,36 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_PENDEPTH_H
+#define DT_PENDEPTH_H
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+class DT_GJK;
+class DT_Convex;
+
+bool penDepth(const DT_GJK& gjk, const DT_Convex& a, const DT_Convex& b,
+ MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
+
+#endif
diff --git a/extern/solid/src/convex/DT_Point.cpp b/extern/solid/src/convex/DT_Point.cpp
new file mode 100644
index 00000000000..770fe7775b7
--- /dev/null
+++ b/extern/solid/src/convex/DT_Point.cpp
@@ -0,0 +1,36 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Point.h"
+
+MT_Scalar DT_Point::supportH(const MT_Vector3& v) const
+{
+ return v.dot(m_point);
+}
+
+MT_Point3 DT_Point::support(const MT_Vector3& v) const
+{
+ return m_point;
+}
+
+
diff --git a/extern/solid/src/convex/DT_Point.h b/extern/solid/src/convex/DT_Point.h
new file mode 100644
index 00000000000..b35d158ee53
--- /dev/null
+++ b/extern/solid/src/convex/DT_Point.h
@@ -0,0 +1,46 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_POINT_H
+#define DT_POINT_H
+
+#include "DT_Convex.h"
+
+class DT_Point : public DT_Convex {
+public:
+ DT_Point(const MT_Point3& point) : m_point(point) {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+private:
+ MT_Point3 m_point;
+};
+
+#endif
+
+
+
+
+
+
diff --git a/extern/solid/src/convex/DT_Polyhedron.cpp b/extern/solid/src/convex/DT_Polyhedron.cpp
new file mode 100644
index 00000000000..f48ac6e4b6d
--- /dev/null
+++ b/extern/solid/src/convex/DT_Polyhedron.cpp
@@ -0,0 +1,415 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Polyhedron.h"
+
+#ifdef QHULL
+
+extern "C" {
+#include <qhull/qhull_a.h>
+}
+
+#include <vector>
+#include <new>
+
+typedef std::vector<MT_Point3> T_VertexBuf;
+typedef std::vector<DT_Index> T_IndexBuf;
+typedef std::vector<T_IndexBuf> T_MultiIndexBuf;
+
+static char options[] = "qhull Qts i Tv";
+
+#define DK_HIERARCHY
+
+T_IndexBuf *adjacency_graph(DT_Count count, const MT_Point3 *verts, const char *flags)
+{
+ int curlong, totlong, exitcode;
+
+ facetT *facet;
+ vertexT *vertex;
+ vertexT **vertexp;
+
+ std::vector<MT::Tuple3<coordT> > array;
+ T_IndexBuf index;
+ DT_Index i;
+ for (i = 0; i != count; ++i)
+ {
+ if (flags == 0 || flags[i])
+ {
+ array.push_back(MT::Tuple3<coordT>(verts[i]));
+ index.push_back(i);
+ }
+ }
+
+ qh_init_A(stdin, stdout, stderr, 0, NULL);
+ if ((exitcode = setjmp(qh errexit)))
+ {
+ exit(exitcode);
+ }
+ qh_initflags(options);
+ qh_init_B(array[0], array.size(), 3, False);
+ qh_qhull();
+ qh_check_output();
+
+ T_IndexBuf *indexBuf = new T_IndexBuf[count];
+ FORALLfacets
+ {
+ setT *vertices = qh_facet3vertex(facet);
+
+ T_IndexBuf facetIndices;
+
+ FOREACHvertex_(vertices)
+ {
+ facetIndices.push_back(index[qh_pointid(vertex->point)]);
+ }
+ int i, j;
+ for (i = 0, j = facetIndices.size()-1; i < (int)facetIndices.size(); j = i++)
+ {
+ indexBuf[facetIndices[j]].push_back(facetIndices[i]);
+ }
+ }
+
+
+ qh NOerrexit = True;
+ qh_freeqhull(!qh_ALL);
+ qh_memfreeshort(&curlong, &totlong);
+
+ return indexBuf;
+}
+
+T_IndexBuf *simplex_adjacency_graph(DT_Count count, const char *flags)
+{
+ T_IndexBuf *indexBuf = new T_IndexBuf[count];
+
+ DT_Index index[4];
+
+ DT_Index k = 0;
+ DT_Index i;
+ for (i = 0; i != count; ++i)
+ {
+ if (flags == 0 || flags[i])
+ {
+ index[k++] = i;
+ }
+ }
+
+ assert(k <= 4);
+
+ for (i = 0; i != k; ++i)
+ {
+ DT_Index j;
+ for (j = 0; j != k; ++j)
+ {
+ if (i != j)
+ {
+ indexBuf[index[i]].push_back(index[j]);
+ }
+ }
+ }
+
+ return indexBuf;
+}
+
+#ifdef DK_HIERARCHY
+
+void prune(DT_Count count, T_MultiIndexBuf *cobound)
+{
+ DT_Index i;
+ for (i = 0; i != count; ++i)
+ {
+ assert(cobound[i].size());
+
+ DT_Index j;
+ for (j = 0; j != cobound[i].size() - 1; ++j)
+ {
+ T_IndexBuf::iterator it = cobound[i][j].begin();
+ while (it != cobound[i][j].end())
+ {
+ T_IndexBuf::iterator jt =
+ std::find(cobound[i][j+1].begin(), cobound[i][j+1].end(), *it);
+
+ if (jt != cobound[i][j+1].end())
+ {
+ std::swap(*it, cobound[i][j].back());
+ cobound[i][j].pop_back();
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+ }
+}
+
+#endif
+
+DT_Polyhedron::DT_Polyhedron(const DT_VertexBase *base, DT_Count count, const DT_Index *indices)
+{
+ assert(count);
+
+ std::vector<MT_Point3> vertexBuf;
+ DT_Index i;
+ for (i = 0; i != count; ++i)
+ {
+ vertexBuf.push_back((*base)[indices[i]]);
+ }
+
+ T_IndexBuf *indexBuf = count > 4 ? adjacency_graph(count, &vertexBuf[0], 0) : simplex_adjacency_graph(count, 0);
+
+ std::vector<MT_Point3> pointBuf;
+
+ for (i = 0; i != count; ++i)
+ {
+ if (!indexBuf[i].empty())
+ {
+ pointBuf.push_back(vertexBuf[i]);
+ }
+ }
+
+ delete [] indexBuf;
+
+ m_count = pointBuf.size();
+ m_verts = new MT_Point3[m_count];
+ std::copy(pointBuf.begin(), pointBuf.end(), &m_verts[0]);
+
+ T_MultiIndexBuf *cobound = new T_MultiIndexBuf[m_count];
+ char *flags = new char[m_count];
+ std::fill(&flags[0], &flags[m_count], 1);
+
+ DT_Count num_layers = 0;
+ DT_Count layer_count = m_count;
+ while (layer_count > 4)
+ {
+ T_IndexBuf *indexBuf = adjacency_graph(m_count, m_verts, flags);
+
+ DT_Index i;
+ for (i = 0; i != m_count; ++i)
+ {
+ if (flags[i])
+ {
+ assert(!indexBuf[i].empty());
+ cobound[i].push_back(indexBuf[i]);
+ }
+ }
+
+ ++num_layers;
+
+ delete [] indexBuf;
+
+ std::fill(&flags[0], &flags[m_count], 0);
+
+ for (i = 0; i != m_count; ++i)
+ {
+ if (cobound[i].size() == num_layers)
+ {
+ T_IndexBuf& curr_cobound = cobound[i].back();
+ if (!flags[i] && curr_cobound.size() <= 8)
+ {
+ DT_Index j;
+ for (j = 0; j != curr_cobound.size(); ++j)
+ {
+ flags[curr_cobound[j]] = 1;
+ }
+ }
+ }
+ }
+
+ layer_count = 0;
+
+ for (i = 0; i != m_count; ++i)
+ {
+ if (flags[i])
+ {
+ ++layer_count;
+ }
+ }
+ }
+
+ indexBuf = simplex_adjacency_graph(m_count, flags);
+
+ for (i = 0; i != m_count; ++i)
+ {
+ if (flags[i])
+ {
+ assert(!indexBuf[i].empty());
+ cobound[i].push_back(indexBuf[i]);
+ }
+ }
+
+ ++num_layers;
+
+ delete [] indexBuf;
+ delete [] flags;
+
+
+
+#ifdef DK_HIERARCHY
+ prune(m_count, cobound);
+#endif
+
+ m_cobound = new T_MultiIndexArray[m_count];
+
+ for (i = 0; i != m_count; ++i)
+ {
+ new (&m_cobound[i]) T_MultiIndexArray(cobound[i].size());
+
+ DT_Index j;
+ for (j = 0; j != cobound[i].size(); ++j)
+ {
+ new (&m_cobound[i][j]) DT_IndexArray(cobound[i][j].size(), &cobound[i][j][0]);
+ }
+ }
+
+ delete [] cobound;
+
+ m_start_vertex = 0;
+ while (m_cobound[m_start_vertex].size() != num_layers)
+ {
+ ++m_start_vertex;
+ assert(m_start_vertex < m_count);
+ }
+
+ m_curr_vertex = m_start_vertex;
+}
+
+
+DT_Polyhedron::~DT_Polyhedron()
+{
+ delete [] m_verts;
+ delete [] m_cobound;
+}
+
+#ifdef DK_HIERARCHY
+
+MT_Scalar DT_Polyhedron::supportH(const MT_Vector3& v) const
+{
+ m_curr_vertex = m_start_vertex;
+ MT_Scalar d = (*this)[m_curr_vertex].dot(v);
+ MT_Scalar h = d;
+ int curr_layer;
+ for (curr_layer = m_cobound[m_start_vertex].size(); curr_layer != 0; --curr_layer)
+ {
+ const DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][curr_layer-1];
+ DT_Index i;
+ for (i = 0; i != curr_cobound.size(); ++i)
+ {
+ d = (*this)[curr_cobound[i]].dot(v);
+ if (d > h)
+ {
+ m_curr_vertex = curr_cobound[i];
+ h = d;
+ }
+ }
+ }
+
+ return h;
+}
+
+MT_Point3 DT_Polyhedron::support(const MT_Vector3& v) const
+{
+ m_curr_vertex = m_start_vertex;
+ MT_Scalar d = (*this)[m_curr_vertex].dot(v);
+ MT_Scalar h = d;
+ int curr_layer;
+ for (curr_layer = m_cobound[m_start_vertex].size(); curr_layer != 0; --curr_layer)
+ {
+ const DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][curr_layer-1];
+ DT_Index i;
+ for (i = 0; i != curr_cobound.size(); ++i)
+ {
+ d = (*this)[curr_cobound[i]].dot(v);
+ if (d > h)
+ {
+ m_curr_vertex = curr_cobound[i];
+ h = d;
+ }
+ }
+ }
+
+ return (*this)[m_curr_vertex];
+}
+
+#else
+
+MT_Scalar DT_Polyhedron::supportH(const MT_Vector3& v) const
+{
+ int last_vertex = -1;
+ MT_Scalar d = (*this)[m_curr_vertex].dot(v);
+ MT_Scalar h = d;
+
+ for (;;)
+ {
+ DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][0];
+ int i = 0, n = curr_cobound.size();
+ while (i != n &&
+ (curr_cobound[i] == last_vertex ||
+ (d = (*this)[curr_cobound[i]].dot(v)) - h <= MT_abs(h) * MT_EPSILON))
+ {
+ ++i;
+ }
+
+ if (i == n)
+ {
+ break;
+ }
+
+ last_vertex = m_curr_vertex;
+ m_curr_vertex = curr_cobound[i];
+ h = d;
+ }
+ return h;
+}
+
+MT_Point3 DT_Polyhedron::support(const MT_Vector3& v) const
+{
+ int last_vertex = -1;
+ MT_Scalar d = (*this)[m_curr_vertex].dot(v);
+ MT_Scalar h = d;
+
+ for (;;)
+ {
+ DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][0];
+ int i = 0, n = curr_cobound.size();
+ while (i != n &&
+ (curr_cobound[i] == last_vertex ||
+ (d = (*this)[curr_cobound[i]].dot(v)) - h <= MT_abs(h) * MT_EPSILON))
+ {
+ ++i;
+ }
+
+ if (i == n)
+ {
+ break;
+ }
+
+ last_vertex = m_curr_vertex;
+ m_curr_vertex = curr_cobound[i];
+ h = d;
+ }
+ return (*this)[m_curr_vertex];
+}
+
+#endif
+
+#endif
+
diff --git a/extern/solid/src/convex/DT_Polyhedron.h b/extern/solid/src/convex/DT_Polyhedron.h
new file mode 100644
index 00000000000..58c991bd152
--- /dev/null
+++ b/extern/solid/src/convex/DT_Polyhedron.h
@@ -0,0 +1,76 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_POLYHEDRON_H
+#define DT_POLYHEDRON_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+# if HAVE_QHULL_QHULL_A_H
+# define QHULL
+# endif
+#endif
+
+
+#ifdef QHULL
+
+#include "DT_Convex.h"
+#include "DT_IndexArray.h"
+#include "DT_VertexBase.h"
+
+class DT_Polyhedron : public DT_Convex {
+ typedef DT_Array<DT_IndexArray> T_MultiIndexArray;
+public:
+ DT_Polyhedron()
+ : m_verts(0),
+ m_cobound(0)
+ {}
+
+ DT_Polyhedron(const DT_VertexBase *base, DT_Count count, const DT_Index *indices);
+
+ virtual ~DT_Polyhedron();
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+ const MT_Point3& operator[](int i) const { return m_verts[i]; }
+ DT_Count numVerts() const { return m_count; }
+
+private:
+ DT_Count m_count;
+ MT_Point3 *m_verts;
+ T_MultiIndexArray *m_cobound;
+ DT_Index m_start_vertex;
+ mutable DT_Index m_curr_vertex;
+};
+
+#else
+
+#include "DT_Polytope.h"
+
+typedef DT_Polytope DT_Polyhedron;
+
+#endif
+
+#endif
+
diff --git a/extern/solid/src/convex/DT_Polytope.cpp b/extern/solid/src/convex/DT_Polytope.cpp
new file mode 100644
index 00000000000..e757c3bfdb4
--- /dev/null
+++ b/extern/solid/src/convex/DT_Polytope.cpp
@@ -0,0 +1,69 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Polytope.h"
+
+MT_BBox DT_Polytope::bbox() const
+{
+ MT_BBox bbox = (*this)[0];
+ DT_Index i;
+ for (i = 1; i < numVerts(); ++i)
+ {
+ bbox = bbox.hull((*this)[i]);
+ }
+ return bbox;
+}
+
+MT_Scalar DT_Polytope::supportH(const MT_Vector3& v) const
+{
+ int c = 0;
+ MT_Scalar h = (*this)[0].dot(v), d;
+ DT_Index i;
+ for (i = 1; i < numVerts(); ++i)
+ {
+ if ((d = (*this)[i].dot(v)) > h)
+ {
+ c = i;
+ h = d;
+ }
+ }
+ return h;
+}
+
+MT_Point3 DT_Polytope::support(const MT_Vector3& v) const
+{
+ int c = 0;
+ MT_Scalar h = (*this)[0].dot(v), d;
+ DT_Index i;
+ for (i = 1; i < numVerts(); ++i)
+ {
+ if ((d = (*this)[i].dot(v)) > h)
+ {
+ c = i;
+ h = d;
+ }
+ }
+ return (*this)[c];
+}
+
+
diff --git a/extern/solid/src/convex/DT_Polytope.h b/extern/solid/src/convex/DT_Polytope.h
new file mode 100644
index 00000000000..c715598defe
--- /dev/null
+++ b/extern/solid/src/convex/DT_Polytope.h
@@ -0,0 +1,51 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_POLYTOPE_H
+#define DT_POLYTOPE_H
+
+#include "DT_Convex.h"
+#include "DT_IndexArray.h"
+#include "DT_VertexBase.h"
+
+class DT_Polytope : public DT_Convex {
+public:
+ DT_Polytope() {}
+ DT_Polytope(const DT_VertexBase *base, DT_Count count, const DT_Index *indices)
+ : m_base(base),
+ m_index(count, indices)
+ {}
+
+ virtual MT_BBox bbox() const;
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+ MT_Point3 operator[](int i) const { return (*m_base)[m_index[i]]; }
+ DT_Count numVerts() const { return m_index.size(); }
+
+protected:
+ const DT_VertexBase *m_base;
+ DT_IndexArray m_index;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Shape.h b/extern/solid/src/convex/DT_Shape.h
new file mode 100644
index 00000000000..d48942fe515
--- /dev/null
+++ b/extern/solid/src/convex/DT_Shape.h
@@ -0,0 +1,72 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_SHAPE_H
+#define DT_SHAPE_H
+
+#include <algorithm>
+
+#include "MT_BBox.h"
+
+#include "MT_Transform.h"
+
+class DT_Object;
+
+enum DT_ShapeType {
+ COMPLEX,
+ CONVEX
+};
+
+class DT_Shape {
+public:
+ virtual ~DT_Shape() {}
+ virtual DT_ShapeType getType() const = 0;
+ virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin) const = 0;
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& param, MT_Vector3& normal) const = 0;
+
+protected:
+ DT_Shape() {}
+};
+
+typedef bool (*Intersect)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3&);
+
+typedef bool (*Common_point)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3&, MT_Point3&, MT_Point3&);
+
+typedef bool (*Penetration_depth)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Vector3&, MT_Point3&, MT_Point3&);
+
+typedef MT_Scalar (*Closest_points)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
+ const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
+ MT_Point3&, MT_Point3&);
+
+#endif
+
+
+
+
+
diff --git a/extern/solid/src/convex/DT_Sphere.cpp b/extern/solid/src/convex/DT_Sphere.cpp
new file mode 100644
index 00000000000..3f2443dcf53
--- /dev/null
+++ b/extern/solid/src/convex/DT_Sphere.cpp
@@ -0,0 +1,90 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#include "DT_Sphere.h"
+#include "GEN_MinMax.h"
+
+MT_Scalar DT_Sphere::supportH(const MT_Vector3& v) const
+{
+ return m_radius * v.length();
+}
+
+MT_Point3 DT_Sphere::support(const MT_Vector3& v) const
+{
+ MT_Scalar s = v.length();
+
+ if (s > MT_Scalar(0.0))
+ {
+ s = m_radius / s;
+ return MT_Point3(v[0] * s, v[1] * s, v[2] * s);
+ }
+ else
+ {
+ return MT_Point3(m_radius, MT_Scalar(0.0), MT_Scalar(0.0));
+ }
+}
+
+bool DT_Sphere::ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const
+{
+ MT_Vector3 r = target - source;
+ MT_Scalar delta = -source.dot(r);
+ MT_Scalar r_length2 = r.length2();
+ MT_Scalar sigma = delta * delta - r_length2 * (source.length2() - m_radius * m_radius);
+
+ if (sigma >= MT_Scalar(0.0))
+ // The line trough source and target intersects the sphere.
+ {
+ MT_Scalar sqrt_sigma = MT_sqrt(sigma);
+ // We need only the sign of lambda2, so the division by the positive
+ // r_length2 can be left out.
+ MT_Scalar lambda2 = (delta + sqrt_sigma) /* / r_length2 */ ;
+ if (lambda2 >= MT_Scalar(0.0))
+ // The ray points at the sphere
+ {
+ MT_Scalar lambda1 = (delta - sqrt_sigma) / r_length2;
+ if (lambda1 <= param)
+ // The ray hits the sphere, since
+ // [lambda1, lambda2] overlaps [0, param].
+ {
+ if (lambda1 > MT_Scalar(0.0))
+ {
+ param = lambda1;
+ normal = (source + r * lambda1) / m_radius;
+ // NB: division by m_radius to normalize the normal.
+ }
+ else
+ {
+ param = MT_Scalar(0.0);
+ normal.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/extern/solid/src/convex/DT_Sphere.h b/extern/solid/src/convex/DT_Sphere.h
new file mode 100644
index 00000000000..92386a66f3a
--- /dev/null
+++ b/extern/solid/src/convex/DT_Sphere.h
@@ -0,0 +1,43 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_SPHERE_H
+#define DT_SPHERE_H
+
+#include "DT_Convex.h"
+
+class DT_Sphere : public DT_Convex {
+public:
+ DT_Sphere(MT_Scalar radius) : m_radius(radius) {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const;
+
+protected:
+ MT_Scalar m_radius;
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_Transform.h b/extern/solid/src/convex/DT_Transform.h
new file mode 100644
index 00000000000..a976d48d22b
--- /dev/null
+++ b/extern/solid/src/convex/DT_Transform.h
@@ -0,0 +1,53 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_TRANSFORM_H
+#define DT_TRANSFORM_H
+
+#include "DT_Convex.h"
+
+class DT_Transform : public DT_Convex {
+public:
+ DT_Transform(const MT_Transform& xform, const DT_Convex& child) :
+ m_xform(xform),
+ m_child(child)
+ {}
+
+ virtual MT_Scalar supportH(const MT_Vector3& v) const
+ {
+ return m_child.supportH(v * m_xform.getBasis()) +
+ v.dot(m_xform.getOrigin());
+ }
+
+ virtual MT_Point3 support(const MT_Vector3& v) const
+ {
+ return m_xform(m_child.support(v * m_xform.getBasis()));
+ }
+
+private:
+ const MT_Transform& m_xform;
+ const DT_Convex& m_child;
+};
+
+
+#endif
diff --git a/extern/solid/src/convex/DT_Triangle.cpp b/extern/solid/src/convex/DT_Triangle.cpp
new file mode 100644
index 00000000000..1917910b39d
--- /dev/null
+++ b/extern/solid/src/convex/DT_Triangle.cpp
@@ -0,0 +1,96 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+//#define BACKFACE_CULLING
+
+#include "DT_Triangle.h"
+
+MT_BBox DT_Triangle::bbox() const
+{
+ return MT_BBox((*this)[0]).hull((*this)[1]).hull((*this)[2]);
+}
+
+MT_Scalar DT_Triangle::supportH(const MT_Vector3& v) const
+{
+ return GEN_max(GEN_max(v.dot((*this)[0]), v.dot((*this)[1])), v.dot((*this)[2]));
+}
+
+MT_Point3 DT_Triangle::support(const MT_Vector3& v) const
+{
+ MT_Vector3 dots(v.dot((*this)[0]), v.dot((*this)[1]), v.dot((*this)[2]));
+
+ return (*this)[dots.maxAxis()];
+}
+
+bool DT_Triangle::ray_cast(const MT_Point3& source, const MT_Point3& target,
+ MT_Scalar& param, MT_Vector3& normal) const
+{
+ MT_Vector3 d1 = (*this)[1] - (*this)[0];
+ MT_Vector3 d2 = (*this)[2] - (*this)[0];
+ MT_Vector3 n = d1.cross(d2);
+ MT_Vector3 r = target - source;
+ MT_Scalar delta = -r.dot(n);
+
+ MT_Scalar rounding_error = GEN_max(GEN_max(MT_abs(n[0]), MT_abs(n[1])), MT_abs(n[2])) * MT_EPSILON;
+
+#ifdef BACKFACE_CULLING
+ if (delta > rounding_error)
+#else
+ if (MT_abs(delta) > rounding_error)
+#endif
+ // The ray is not parallel to the triangle's plane.
+ // (Coplanar rays are ignored.)
+ {
+ MT_Vector3 b = source - (*this)[0];
+ MT_Scalar lambda = b.dot(n) / delta;
+
+ if (MT_Scalar(0.0) <= lambda && lambda <= param)
+ // The ray intersects the triangle's plane.
+ {
+ MT_Vector3 u = b.cross(r);
+ MT_Scalar mu1 = d2.dot(u) / delta;
+
+ if (MT_Scalar(0.0) <= mu1 && mu1 <= MT_Scalar(1.0))
+ {
+ MT_Scalar mu2 = -d1.dot(u) / delta;
+
+ if (MT_Scalar(0.0) <= mu2 && mu1 + mu2 <= MT_Scalar(1.0))
+ // The ray intersects the triangle.
+ {
+ param = lambda;
+ // Return a normal that points at the source.
+#ifdef BACKFACE_CULLING
+ normal = n;
+#else
+ normal = delta > MT_Scalar(0.0) ? n : -n;
+#endif
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/extern/solid/src/convex/DT_Triangle.h b/extern/solid/src/convex/DT_Triangle.h
new file mode 100644
index 00000000000..4192b5629ac
--- /dev/null
+++ b/extern/solid/src/convex/DT_Triangle.h
@@ -0,0 +1,63 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_TRIANGLE_H
+#define DT_TRIANGLE_H
+
+#include "SOLID_types.h"
+
+#include "DT_Convex.h"
+#include "DT_IndexArray.h"
+#include "DT_VertexBase.h"
+
+class DT_Triangle : public DT_Convex {
+public:
+ DT_Triangle(const DT_VertexBase *base, DT_Index i0, DT_Index i1, DT_Index i2) :
+ m_base(base)
+ {
+ m_index[0] = i0;
+ m_index[1] = i1;
+ m_index[2] = i2;
+ }
+
+ DT_Triangle(const DT_VertexBase *base, const DT_Index *index) :
+ m_base(base)
+ {
+ m_index[0] = index[0];
+ m_index[1] = index[1];
+ m_index[2] = index[2];
+ }
+
+ virtual MT_BBox bbox() const;
+ virtual MT_Scalar supportH(const MT_Vector3& v) const;
+ virtual MT_Point3 support(const MT_Vector3& v) const;
+ virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& lambda, MT_Vector3& normal) const;
+
+ MT_Point3 operator[](int i) const { return (*m_base)[m_index[i]]; }
+
+private:
+ const DT_VertexBase *m_base;
+ DT_Index m_index[3];
+};
+
+#endif
diff --git a/extern/solid/src/convex/DT_VertexBase.h b/extern/solid/src/convex/DT_VertexBase.h
new file mode 100644
index 00000000000..37646fdd935
--- /dev/null
+++ b/extern/solid/src/convex/DT_VertexBase.h
@@ -0,0 +1,84 @@
+/*
+ * SOLID - Software Library for Interference Detection
+ *
+ * Copyright (C) 2001-2003 Dtecta. All rights reserved.
+ *
+ * This library may be distributed under the terms of the Q Public License
+ * (QPL) as defined by Trolltech AS of Norway and appearing in the file
+ * LICENSE.QPL included in the packaging of this file.
+ *
+ * This library may be distributed and/or modified under the terms of the
+ * GNU General Public License (GPL) version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Commercial use or any other use of this library not covered by either
+ * the QPL or the GPL requires an additional license from Dtecta.
+ * Please contact info@dtecta.com for enquiries about the terms of commercial
+ * use of this library.
+ */
+
+#ifndef DT_VERTEXBASE_H
+#define DT_VERTEXBASE_H
+
+#include "MT_Point3.h"
+
+#include <vector>
+
+class DT_Complex;
+
+typedef std::vector<DT_Complex *>DT_ComplexList;
+
+class DT_VertexBase {
+public:
+ explicit DT_VertexBase(const void *base = 0, DT_Size stride = 0, bool owner = false) :
+ m_base((char *)base),
+ m_stride(stride ? stride : 3 * sizeof(DT_Scalar)),
+ m_owner(owner)
+ {}
+
+ ~DT_VertexBase()
+ {
+ if (m_owner)
+ {
+ delete [] m_base;
+ }
+ }
+
+ MT_Point3 operator[](DT_Index i) const
+ {
+ return MT_Point3(reinterpret_cast<DT_Scalar *>(m_base + i * m_stride));
+ }
+
+ void setPointer(const void *base, bool owner = false)
+ {
+ m_base = (char *)base;
+ m_owner = owner;
+ }
+
+ const void *getPointer() const { return m_base; }
+ bool isOwner() const { return m_owner; }
+
+ void addComplex(DT_Complex *complex) const { m_complexList.push_back(complex); }
+ void removeComplex(DT_Complex *complex) const
+ {
+ DT_ComplexList::iterator it = std::find(m_complexList.begin(), m_complexList.end(), complex);
+ if (it != m_complexList.end())
+ {
+ m_complexList.erase(it);
+ }
+ }
+
+ const DT_ComplexList& getComplexList() const { return m_complexList; }
+
+private:
+ char *m_base;
+ DT_Size m_stride;
+ bool m_owner;
+ mutable DT_ComplexList m_complexList;
+};
+
+#endif
diff --git a/extern/solid/src/convex/Makefile b/extern/solid/src/convex/Makefile
new file mode 100644
index 00000000000..75fa578a292
--- /dev/null
+++ b/extern/solid/src/convex/Makefile
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = solid_convex
+DIR = $(OCGDIR)/extern/$(LIBNAME)
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
+CPPFLAGS += -DQHULL -DUSE_DOUBLES
+
+include nan_compile.mk
+
+
diff --git a/intern/bsp/test/Makefile b/intern/bsp/test/Makefile
index 91e4497b267..eebf7470a0f 100644
--- a/intern/bsp/test/Makefile
+++ b/intern/bsp/test/Makefile
@@ -47,7 +47,7 @@ SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
SLIBS += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
SLIBS += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
-ifeq ($(OS),$(findstring $(OS), "darwin linux freebsd openbsd"))
+ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
LLIBS = -L/usr/X11R6/lib -lglut -pthread -lXi -lXmu
endif
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 3b5f6a0caf9..7bdca7339fc 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -38,7 +38,8 @@
#include <stdarg.h>
/* mmap exception */
-#if defined(WIN32)
+#if defined(AMIGA) || defined(__BeOS)
+#elif defined(WIN32)
#include <sys/types.h>
#include "mmap_win.h"
#else
@@ -291,6 +292,9 @@ void *MEM_callocN(unsigned int len, const char *str)
/* note; mmap returns zero'd memory */
void *MEM_mapallocN(unsigned int len, const char *str)
{
+#if defined(AMIGA) || defined(__BeOS)
+ return MEM_callocN(len, str);
+#else
MemHead *memh;
mem_lock_thread();
@@ -325,6 +329,7 @@ void *MEM_mapallocN(unsigned int len, const char *str)
print_error("Mapalloc returns nill, fallback to regular malloc: len=%d in %s, total %u\n",len, str, mmap_in_use);
return MEM_callocN(len, str);
}
+#endif
}
/* Memory statistics print */
@@ -584,6 +589,10 @@ static void rem_memblock(MemHead *memh)
totblock--;
mem_in_use -= memh->len;
+#if defined(AMIGA) || defined(__BeOS)
+ free(memh);
+#else
+
if(memh->mmap) {
mmap_in_use -= memh->len;
if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
@@ -594,6 +603,7 @@ static void rem_memblock(MemHead *memh)
memset(memh+1, 255, memh->len);
free(memh);
}
+#endif
}
static void MemorY_ErroR(const char *block, const char *error)
diff --git a/intern/iksolver/test/Makefile b/intern/iksolver/test/Makefile
index ed867ba2a73..4ab317f9e9f 100644
--- a/intern/iksolver/test/Makefile
+++ b/intern/iksolver/test/Makefile
@@ -46,7 +46,7 @@ LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libiksolver.a
SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
-ifeq ($(OS),$(findstring $(OS), "darwin linux freebsd openbsd"))
+ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
LLIBS = -L/usr/X11R6/lib -lglut -pthread
endif
diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h
index c6d299d19fd..899a2731588 100644
--- a/intern/moto/include/MT_Matrix3x3.h
+++ b/intern/moto/include/MT_Matrix3x3.h
@@ -98,18 +98,6 @@ public:
m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
}
- void setValue3x3(const float *m) {
- m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
- m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
- m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
- }
-
- void setValue3x3(const double *m) {
- m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
- m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
- m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
- }
-
void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz,
MT_Scalar yx, MT_Scalar yy, MT_Scalar yz,
MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) {
@@ -206,18 +194,6 @@ public:
*m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m = 0.0;
}
- void getValue3x3(float *m) const {
- *m++ = (float) m_el[0][0]; *m++ = (float) m_el[1][0]; *m++ = (float) m_el[2][0];
- *m++ = (float) m_el[0][1]; *m++ = (float) m_el[1][1]; *m++ = (float) m_el[2][1];
- *m++ = (float) m_el[0][2]; *m++ = (float) m_el[1][2]; *m++ = (float) m_el[2][2];
- }
-
- void getValue3x3(double *m) const {
- *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0];
- *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1];
- *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2];
- }
-
MT_Quaternion getRotation() const;
MT_Matrix3x3& operator*=(const MT_Matrix3x3& m);
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
index 646b1a853dc..dcc52e2a3e7 100644
--- a/intern/string/intern/STR_String.cpp
+++ b/intern/string/intern/STR_String.cpp
@@ -559,8 +559,7 @@ STR_String& STR_String::TrimLeft()
{
int skip;
assertd(pData != NULL);
- for (skip=0; isSpace(pData[skip]); skip++, Len--)
- {};
+ for (skip=0; isSpace(pData[skip]); skip++, Len--);
memmove(pData, pData+skip, Len+1);
return *this;
}
@@ -599,8 +598,7 @@ STR_String& STR_String::TrimLeft(char *set)
{
int skip;
assertd(pData != NULL);
- for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--)
- {};
+ for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--);
memmove(pData, pData+skip, Len+1);
return *this;
}
diff --git a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
index 341275a5b5a..e66693cc86f 100644
--- a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
+++ b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
@@ -367,42 +367,6 @@
>
</File>
</Filter>
- <Filter
- Name="generic"
- >
- <File
- RelativePath="..\..\..\source\blender\python\generic\BGL.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\bpy_internal_import.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\euler.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\Geometry.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\Mathutils.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\matrix.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\quat.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\python\generic\vector.c"
- >
- </File>
- </Filter>
</Filter>
<Filter
Name="Header Files"
diff --git a/projectfiles_vc9/blender/blender.sln b/projectfiles_vc9/blender/blender.sln
index 21610cb3df5..6b58bcfc020 100644
--- a/projectfiles_vc9/blender/blender.sln
+++ b/projectfiles_vc9/blender/blender.sln
@@ -9,6 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{98330220-47A6-42E0-9DE4-AD0FF5D204D6} = {98330220-47A6-42E0-9DE4-AD0FF5D204D6}
{BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE} = {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE}
{C66F722C-46BE-40C9-ABAE-2EAC7A697EB8} = {C66F722C-46BE-40C9-ABAE-2EAC7A697EB8}
+ {9625642D-6F20-4FB6-A089-BE7441B223E3} = {9625642D-6F20-4FB6-A089-BE7441B223E3}
{D1A9312F-4557-4982-A0F4-4D08508235F4} = {D1A9312F-4557-4982-A0F4-4D08508235F4}
{884D8731-654C-4C7F-9A75-8F37A305BE1E} = {884D8731-654C-4C7F-9A75-8F37A305BE1E}
{E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}
@@ -20,8 +21,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{EADC3C5A-6C51-4F03-8038-1553E7D7F740} = {EADC3C5A-6C51-4F03-8038-1553E7D7F740}
{B093415D-C0F6-4E76-8F5A-6BC1917BCE9E} = {B093415D-C0F6-4E76-8F5A-6BC1917BCE9E}
{DB6BE55D-B6D9-494D-856A-8764FF7BA91D} = {DB6BE55D-B6D9-494D-856A-8764FF7BA91D}
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B} = {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}
{0A73055E-4DED-40CD-9F72-9093ED3EEC7E} = {0A73055E-4DED-40CD-9F72-9093ED3EEC7E}
{09222F5E-1625-4FF3-A89A-384D16875EE5} = {09222F5E-1625-4FF3-A89A-384D16875EE5}
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD} = {D696C86B-0B53-4471-A50D-5B983A6FA4AD}
{138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
{415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
{106AE171-0083-41D6-A949-20DB0E8DC251} = {106AE171-0083-41D6-A949-20DB0E8DC251}
@@ -43,15 +46,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{E90C7BC2-CF30-4A60-A8F2-0050D592E358} = {E90C7BC2-CF30-4A60-A8F2-0050D592E358}
{8B8D4FC3-3234-4E54-8376-5AB83D00D164} = {8B8D4FC3-3234-4E54-8376-5AB83D00D164}
{4B6AFCC5-968C-424A-8F20-76E41B3BEF74} = {4B6AFCC5-968C-424A-8F20-76E41B3BEF74}
+ {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4}
{EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9} = {EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9}
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49} = {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA} = {5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}
{E86B7BDE-C33C-4E55-9433-E74C141D7538} = {E86B7BDE-C33C-4E55-9433-E74C141D7538}
{32CC75E2-EE85-45E6-8E3D-513F58464F43} = {32CC75E2-EE85-45E6-8E3D-513F58464F43}
{DFE7F3E3-E62A-4677-B666-DF0DDF70C359} = {DFE7F3E3-E62A-4677-B666-DF0DDF70C359}
{9A307EE5-CD77-47BC-BD87-62508C7E19D8} = {9A307EE5-CD77-47BC-BD87-62508C7E19D8}
{AB590CED-F71F-4A17-A89B-18583ECD633D} = {AB590CED-F71F-4A17-A89B-18583ECD633D}
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373}
{1CC733F1-6AB5-4904-8F63-C08C46B79DD9} = {1CC733F1-6AB5-4904-8F63-C08C46B79DD9}
{B789C2F3-279E-4A85-8F0A-7F7AC068E598} = {B789C2F3-279E-4A85-8F0A-7F7AC068E598}
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BKE_blenkernel", "blenkernel\BKE_blenkernel.vcproj", "{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}"
@@ -79,6 +86,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPY_python", "BPY_python\BP
{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BRA_radiosity", "radiosity\BRA_radiosity.vcproj", "{2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BRE_render", "render\BRE_render.vcproj", "{106AE171-0083-41D6-A949-20DB0E8DC251}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNA_makesdna", "makesdna\DNA_makesdna.vcproj", "{E013786A-9575-4F34-81B2-33290357EE87}"
@@ -93,6 +102,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GP_axctl", "..\gameengine\g
{E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F} = {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F}
{6E24BF09-9653-4166-A871-F65CC9E98A9B} = {6E24BF09-9653-4166-A871-F65CC9E98A9B}
{BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE} = {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE}
+ {9625642D-6F20-4FB6-A089-BE7441B223E3} = {9625642D-6F20-4FB6-A089-BE7441B223E3}
{E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}
{51FB3D48-2467-4BFA-A321-D848252B437E} = {51FB3D48-2467-4BFA-A321-D848252B437E}
{31628053-825D-4C06-8A21-D13883489718} = {31628053-825D-4C06-8A21-D13883489718}
@@ -127,6 +137,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenderplayer", "..\gameeng
{98330220-47A6-42E0-9DE4-AD0FF5D204D6} = {98330220-47A6-42E0-9DE4-AD0FF5D204D6}
{BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE} = {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE}
{C66F722C-46BE-40C9-ABAE-2EAC7A697EB8} = {C66F722C-46BE-40C9-ABAE-2EAC7A697EB8}
+ {9625642D-6F20-4FB6-A089-BE7441B223E3} = {9625642D-6F20-4FB6-A089-BE7441B223E3}
{D1A9312F-4557-4982-A0F4-4D08508235F4} = {D1A9312F-4557-4982-A0F4-4D08508235F4}
{E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}
@@ -139,6 +150,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenderplayer", "..\gameeng
{0A73055E-4DED-40CD-9F72-9093ED3EEC7E} = {0A73055E-4DED-40CD-9F72-9093ED3EEC7E}
{09222F5E-1625-4FF3-A89A-384D16875EE5} = {09222F5E-1625-4FF3-A89A-384D16875EE5}
{E013786A-9575-4F34-81B2-33290357EE87} = {E013786A-9575-4F34-81B2-33290357EE87}
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD} = {D696C86B-0B53-4471-A50D-5B983A6FA4AD}
{138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
{415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
{670EC17A-0548-4BBF-A27B-636C7C188139} = {670EC17A-0548-4BBF-A27B-636C7C188139}
@@ -160,13 +172,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenderplayer", "..\gameeng
{E90C7BC2-CF30-4A60-A8F2-0050D592E358} = {E90C7BC2-CF30-4A60-A8F2-0050D592E358}
{8B8D4FC3-3234-4E54-8376-5AB83D00D164} = {8B8D4FC3-3234-4E54-8376-5AB83D00D164}
{4B6AFCC5-968C-424A-8F20-76E41B3BEF74} = {4B6AFCC5-968C-424A-8F20-76E41B3BEF74}
+ {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4}
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49} = {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA} = {5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}
{E86B7BDE-C33C-4E55-9433-E74C141D7538} = {E86B7BDE-C33C-4E55-9433-E74C141D7538}
{32CC75E2-EE85-45E6-8E3D-513F58464F43} = {32CC75E2-EE85-45E6-8E3D-513F58464F43}
{9A307EE5-CD77-47BC-BD87-62508C7E19D8} = {9A307EE5-CD77-47BC-BD87-62508C7E19D8}
{AB590CED-F71F-4A17-A89B-18583ECD633D} = {AB590CED-F71F-4A17-A89B-18583ECD633D}
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373}
{1CC733F1-6AB5-4904-8F63-C08C46B79DD9} = {1CC733F1-6AB5-4904-8F63-C08C46B79DD9}
{B789C2F3-279E-4A85-8F0A-7F7AC068E598} = {B789C2F3-279E-4A85-8F0A-7F7AC068E598}
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KX_blenderhook", "..\gameengine\blenderhook\KX_blenderhook.vcproj", "{8154A59A-CAED-403D-AB94-BC4E7C032666}"
@@ -201,6 +217,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenpluginapi", "blenplugin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_messaging", "..\kernel\gen_messaging\gen_messaging.vcproj", "{727F90AC-ABE6-40BF-8937-C2F2F1D13DEA}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PHY_Sumo", "..\gameengine\physics\PHY_Physics\PHY_Sumo\PHY_Sumo.vcproj", "{9625642D-6F20-4FB6-A089-BE7441B223E3}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PHY_Bullet", "..\gameengine\physics\PHY_Physics\PHY_Bullet\PHY_Bullet.vcproj", "{E90C7BC2-CF30-4A60-A8F2-0050D592E358}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
@@ -212,13 +230,31 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BL_gpu", "gpu\BL_gpu.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEX_Video", "..\gameengine\videotexture\TEX_Video.vcproj", "{670EC17A-0548-4BBF-A27B-636C7C188139}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_broad", "..\..\extern\solid\make\msvc_9_0\broad\broad.vcproj", "{0112CAD5-3584-412A-A2E5-1315A00437B4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_complex", "..\..\extern\solid\make\msvc_9_0\complex\complex.vcproj", "{B83C6BED-11EC-46C8-AFFA-121EEDE94373}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_convex", "..\..\extern\solid\make\msvc_9_0\convex\convex.vcproj", "{524264F4-DF21-4B79-847F-E7CA643ECD0B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_solid", "..\..\extern\solid\make\msvc_9_0\solid.vcproj", "{D696C86B-0B53-4471-A50D-5B983A6FA4AD}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B} = {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}
+ {BAC615B0-F1AF-418B-8D23-A10FD8870D6A} = {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}
+ {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4}
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373}
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_bullet2", "..\..\extern\bullet2\make\msvc_9_0\Bullet.vcproj", "{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_glew", "..\..\extern\glew\make\msvc_9_0\glew.vcproj", "{BAC615B0-F1AF-418B-8D23-A10FD8870D6A}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_qhull", "..\..\extern\qhull\make\msvc_9_0\qhull.vcproj", "{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EXT_build_install_all", "..\..\extern\make\msvc_9_0\build_install_all.vcproj", "{9C71A793-C177-4CAB-8EC5-923D500B39F8}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD} = {D696C86B-0B53-4471-A50D-5B983A6FA4AD}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INT_boolop", "..\..\intern\boolop\make\msvc_9_0\boolop.vcproj", "{EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9}"
@@ -448,6 +484,20 @@ Global
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}.Debug|Win32.Build.0 = BlenderPlayer Debug|Win32
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}.Release|Win32.ActiveCfg = BlenderPlayer Release|Win32
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}.Release|Win32.Build.0 = BlenderPlayer Release|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.3D Plugin Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.3D Plugin Debug|Win32.Build.0 = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.3D Plugin Release|Win32.ActiveCfg = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.3D Plugin Release|Win32.Build.0 = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Debug|Win32.Build.0 = Blender Debug|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Release|Win32.ActiveCfg = Blender Release|Win32
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}.Release|Win32.Build.0 = Blender Release|Win32
{106AE171-0083-41D6-A949-20DB0E8DC251}.3D Plugin Debug|Win32.ActiveCfg = Blender Debug|Win32
{106AE171-0083-41D6-A949-20DB0E8DC251}.3D Plugin Debug|Win32.Build.0 = Blender Debug|Win32
{106AE171-0083-41D6-A949-20DB0E8DC251}.3D Plugin Release|Win32.ActiveCfg = Blender Debug|Win32
@@ -784,6 +834,22 @@ Global
{727F90AC-ABE6-40BF-8937-C2F2F1D13DEA}.Debug|Win32.Build.0 = BlenderPlayer Debug|Win32
{727F90AC-ABE6-40BF-8937-C2F2F1D13DEA}.Release|Win32.ActiveCfg = BlenderPlayer Release|Win32
{727F90AC-ABE6-40BF-8937-C2F2F1D13DEA}.Release|Win32.Build.0 = BlenderPlayer Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.BlenderPlayer Debug|Win32.ActiveCfg = BlenderPlayer Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.BlenderPlayer Debug|Win32.Build.0 = BlenderPlayer Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.BlenderPlayer Release|Win32.ActiveCfg = BlenderPlayer Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.BlenderPlayer Release|Win32.Build.0 = BlenderPlayer Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Release|Win32.ActiveCfg = BlenderPlayer Release|Win32
+ {9625642D-6F20-4FB6-A089-BE7441B223E3}.Release|Win32.Build.0 = BlenderPlayer Release|Win32
{E90C7BC2-CF30-4A60-A8F2-0050D592E358}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
{E90C7BC2-CF30-4A60-A8F2-0050D592E358}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
{E90C7BC2-CF30-4A60-A8F2-0050D592E358}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
@@ -848,6 +914,70 @@ Global
{670EC17A-0548-4BBF-A27B-636C7C188139}.Debug|Win32.Build.0 = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Release|Win32.ActiveCfg = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Release|Win32.Build.0 = Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Release|Win32.Build.0 = 3D Plugin Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
@@ -880,6 +1010,22 @@ Global
{BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Debug|Win32.Build.0 = Blender Debug|Win32
{BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Release|Win32.ActiveCfg = Blender Release|Win32
{BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Release|Win32.Build.0 = Blender Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Release|Win32.Build.0 = 3D Plugin Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Release|Win32.Build.0 = Blender Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Debug|Win32.Build.0 = 3D Plugin Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Release|Win32.ActiveCfg = 3D Plugin Release|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Release|Win32.Build.0 = 3D Plugin Release|Win32
{9C71A793-C177-4CAB-8EC5-923D500B39F8}.3D Plugin Debug|Win32.ActiveCfg = 3D Plugin Debug|Win32
{9C71A793-C177-4CAB-8EC5-923D500B39F8}.3D Plugin Debug|Win32.Build.0 = 3D Plugin Debug|Win32
{9C71A793-C177-4CAB-8EC5-923D500B39F8}.3D Plugin Release|Win32.ActiveCfg = 3D Plugin Release|Win32
diff --git a/projectfiles_vc9/blender/editors/ED_editors.vcproj b/projectfiles_vc9/blender/editors/ED_editors.vcproj
index 5b7b8b4b0ce..aaec7a66a55 100644
--- a/projectfiles_vc9/blender/editors/ED_editors.vcproj
+++ b/projectfiles_vc9/blender/editors/ED_editors.vcproj
@@ -262,10 +262,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\editors\include\ED_pointcache.h"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\editors\include\ED_previewrender.h"
>
</File>
@@ -1347,10 +1343,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\editors\physics\ed_pointcache.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\editors\physics\editparticle.c"
>
</File>
@@ -1359,30 +1351,6 @@
>
</File>
</Filter>
- <Filter
- Name="space_logic"
- >
- <File
- RelativePath="..\..\..\source\blender\editors\space_logic\logic_buttons.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\space_logic\logic_header.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\space_logic\logic_intern.h"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\space_logic\logic_window.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\space_logic\space_logic.c"
- >
- </File>
- </Filter>
</Files>
<Globals>
</Globals>
diff --git a/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj b/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
index 255c66f398d..0f3d2b01030 100644
--- a/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
+++ b/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
@@ -589,6 +589,10 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
+ RelativePath="..\..\..\source\blender\editors\interface\interface_api.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\makesrna\intern\makesrna.c"
>
</File>
@@ -681,10 +685,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna_main_api.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_material.c"
>
</File>
@@ -693,10 +693,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna_mesh_api.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_meta.c"
>
</File>
@@ -713,10 +709,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna_object_api.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_object_force.c"
>
</File>
@@ -737,6 +729,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\makesrna\intern\rna_radio.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_rna.c"
>
</File>
@@ -785,10 +781,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna_ui_api.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_userdef.c"
>
</File>
@@ -805,10 +797,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna_wm_api.c"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_world.c"
>
</File>
diff --git a/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj b/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
index 848316b76d2..d99d14c0979 100644
--- a/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
+++ b/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
@@ -183,10 +183,6 @@
>
</File>
<File
- RelativePath="..\..\..\source\blender\makesrna\intern\rna.cRNA_blender_cpp.h"
- >
- </File>
- <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_brush_gen.c"
>
</File>
@@ -299,6 +295,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_radio_gen.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_rna_gen.c"
>
</File>
diff --git a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj
index b47ff86fafc..654cb567fda 100644
--- a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj
+++ b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj
@@ -43,7 +43,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenfont"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenfont"
PreprocessorDefinitions="WIN32;_LIB;_DEBUG;WITH_GLEXT;WITH_FFMPEG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -119,7 +119,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenfont"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenfont"
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT;WITH_FFMPEG"
StringPooling="true"
BasicRuntimeChecks="0"
diff --git a/projectfiles_vc9/gameengine/converter/KX_converter.vcproj b/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
index c03669cf873..64f8b26c7f7 100644
--- a/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
+++ b/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
@@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -117,7 +117,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,USE_SUMO_SOLID"
StringPooling="true"
RuntimeLibrary="0"
@@ -193,7 +193,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -268,7 +268,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,USE_SUMO_SOLID"
StringPooling="true"
RuntimeLibrary="2"
@@ -344,7 +344,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -419,7 +419,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\ode;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\gameengine\soundsystem\snd_blenderwavecache;..\..\..\source\sumo\include;..\..\..\source\sumo\Fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\gpu;..\..\..\source\blender\windowmanager"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,USE_SUMO_SOLID"
StringPooling="true"
RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj b/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
index 982e58e3af9..a8b94c3f4a0 100644
--- a/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
+++ b/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
@@ -43,7 +43,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -118,7 +118,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="WIN32,_LIB,EXP_PYTHON_EMBEDDING,_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -193,7 +193,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
StringPooling="true"
RuntimeLibrary="2"
@@ -268,7 +268,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
StringPooling="true"
RuntimeLibrary="0"
@@ -343,7 +343,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -418,7 +418,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph;..\..\..\source\blender\blenloader"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
StringPooling="true"
RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
index 3e072aee9ca..fb812c02f44 100644
--- a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
+++ b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
@@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID"
StringPooling="true"
RuntimeLibrary="2"
@@ -118,7 +118,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG;USE_SUMO_SOLID"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -193,7 +193,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="JANCODEPANCO;WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG;USE_SUMO_SOLID;WITH_GLEXT"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -269,7 +269,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT"
StringPooling="true"
RuntimeLibrary="0"
@@ -345,7 +345,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="JANCODEPANCO;WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG;USE_SUMO_SOLID;WITH_GLEXT"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -421,7 +421,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\python\generic;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
+ AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x;..\..\..\source\blender\gpu"
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT"
StringPooling="true"
RuntimeLibrary="0"
@@ -550,6 +550,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\Ketsji\KX_OdePhysicsController.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\Ketsji\KX_PhysicsObjectWrapper.cpp"
>
</File>
@@ -598,6 +602,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\gameengine\Ketsji\KX_SumoPhysicsController.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\gameengine\Ketsji\KX_TimeCategoryLogger.cpp"
>
</File>
diff --git a/release/ui/buttons_data_armature.py b/release/ui/buttons_data_armature.py
index 112724bea91..c536f6bb87d 100644
--- a/release/ui/buttons_data_armature.py
+++ b/release/ui/buttons_data_armature.py
@@ -26,10 +26,10 @@ class DATA_PT_skeleton(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif arm:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if arm:
diff --git a/release/ui/buttons_data_camera.py b/release/ui/buttons_data_camera.py
index 9f3a062b429..db2a1f9db25 100644
--- a/release/ui/buttons_data_camera.py
+++ b/release/ui/buttons_data_camera.py
@@ -26,10 +26,10 @@ class DATA_PT_camera(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif arm:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if cam:
diff --git a/release/ui/buttons_data_curve.py b/release/ui/buttons_data_curve.py
index e60f9591d29..869d29802e1 100644
--- a/release/ui/buttons_data_curve.py
+++ b/release/ui/buttons_data_curve.py
@@ -26,10 +26,10 @@ class DATA_PT_shape_curve(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif curve:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if curve:
diff --git a/release/ui/buttons_data_lamp.py b/release/ui/buttons_data_lamp.py
index a556aceb98d..52a60ce617e 100644
--- a/release/ui/buttons_data_lamp.py
+++ b/release/ui/buttons_data_lamp.py
@@ -36,10 +36,10 @@ class DATA_PT_lamp(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif lamp:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
layout.itemS()
diff --git a/release/ui/buttons_data_lattice.py b/release/ui/buttons_data_lattice.py
index bf2aaad5a97..ad9b1b518b8 100644
--- a/release/ui/buttons_data_lattice.py
+++ b/release/ui/buttons_data_lattice.py
@@ -26,10 +26,10 @@ class DATA_PT_lattice(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif lat:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if lat:
diff --git a/release/ui/buttons_data_mesh.py b/release/ui/buttons_data_mesh.py
index 3360f4c47ad..c103a0f7055 100644
--- a/release/ui/buttons_data_mesh.py
+++ b/release/ui/buttons_data_mesh.py
@@ -26,10 +26,10 @@ class DATA_PT_mesh(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif mesh:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if mesh:
@@ -46,46 +46,6 @@ class DATA_PT_mesh(DataButtonsPanel):
sub.itemR(mesh, "vertex_normal_flip")
sub.itemR(mesh, "double_sided")
- layout.itemR(mesh, "texco_mesh")
-
-
-class DATA_PT_materials(DataButtonsPanel):
- __idname__ = "DATA_PT_materials"
- __label__ = "Materials"
-
- def poll(self, context):
- return (context.object and context.object.type in ('MESH', 'CURVE', 'FONT', 'SURFACE'))
-
- def draw(self, context):
- layout = self.layout
- ob = context.object
-
- row = layout.row()
-
- row.template_list(ob, "materials", "active_material_index")
-
- col = row.column(align=True)
- col.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="")
- col.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
-
- row = layout.row(align=True)
-
- row.itemO("OBJECT_OT_material_slot_assign", text="Assign");
- row.itemO("OBJECT_OT_material_slot_select", text="Select");
- row.itemO("OBJECT_OT_material_slot_deselect", text="Deselect");
-
- layout.itemS()
-
- box= layout.box()
-
- row = box.row()
- row.template_list(ob, "materials", "active_material_index", compact=True)
-
- subrow = row.row(align=True)
- subrow.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="")
- subrow.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="")
-
-
+ layout.itemR(mesh, "texco_mesh")
+
bpy.types.register(DATA_PT_mesh)
-bpy.types.register(DATA_PT_materials)
-
diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py
index 366f2b8a86b..ecb0590f8e5 100644
--- a/release/ui/buttons_data_modifier.py
+++ b/release/ui/buttons_data_modifier.py
@@ -23,68 +23,68 @@ class DATA_PT_modifiers(DataButtonsPanel):
if box:
if md.type == 'ARMATURE':
- self.armature(box, ob, md)
+ self.armature(box, md)
if md.type == 'ARRAY':
- self.array(box, ob, md)
+ self.array(box, md)
if md.type == 'BEVEL':
- self.bevel(box, ob, md)
+ self.bevel(box, md)
if md.type == 'BOOLEAN':
- self.boolean(box, ob, md)
+ self.boolean(box, md)
if md.type == 'BUILD':
- self.build(box, ob, md)
+ self.build(box, md)
if md.type == 'CAST':
- self.cast(box, ob, md)
+ self.cast(box, md)
if md.type == 'CLOTH':
- self.cloth(box, ob, md)
+ self.cloth(box, md)
if md.type == 'COLLISION':
- self.collision(box, ob, md)
+ self.collision(box, md)
if md.type == 'CURVE':
- self.curve(box, ob, md)
+ self.curve(box, md)
if md.type == 'DECIMATE':
- self.decimate(box, ob, md)
+ self.decimate(box, md)
if md.type == 'DISPLACE':
- self.displace(box, ob, md)
+ self.displace(box, md)
if md.type == 'EDGE_SPLIT':
- self.edgesplit(box, ob, md)
+ self.edgesplit(box, md)
if md.type == 'EXPLODE':
- self.explode(box, ob, md)
+ self.explode(box, md)
if md.type == 'FLUID_SIMULATION':
- self.fluid(box, ob, md)
+ self.fluid(box, md)
if md.type == 'HOOK':
- self.hook(box, ob, md)
+ self.hook(box, md)
if md.type == 'LATTICE':
- self.lattice(box, ob, md)
+ self.lattice(box, md)
if md.type == 'MASK':
- self.mask(box, ob, md)
+ self.mask(box, md)
if md.type == 'MESH_DEFORM':
- self.mesh_deform(box, ob, md)
+ self.mesh_deform(box, md)
if md.type == 'MIRROR':
- self.mirror(box, ob, md)
+ self.mirror(box, md)
if md.type == 'MULTIRES':
- self.multires(box, ob, md)
+ self.multires(box, md)
if md.type == 'PARTICLE_INSTANCE':
- self.particleinstance(box, ob, md)
+ self.particleinstance(box, md)
if md.type == 'PARTICLE_SYSTEM':
- self.particlesystem(box, ob, md)
+ self.particlesystem(box, md)
if md.type == 'SHRINKWRAP':
- self.shrinkwrap(box, ob, md)
+ self.shrinkwrap(box, md)
if md.type == 'SIMPLE_DEFORM':
- self.simpledeform(box, ob, md)
+ self.simpledeform(box, md)
if md.type == 'SMOOTH':
- self.smooth(box, ob, md)
+ self.smooth(box, md)
if md.type == 'SOFTBODY':
- self.softbody(box, ob, md)
+ self.softbody(box, md)
if md.type == 'SUBSURF':
- self.subsurf(box, ob, md)
+ self.subsurf(box, md)
if md.type == 'UV_PROJECT':
- self.uvproject(box, ob, md)
+ self.uvproject(box, md)
if md.type == 'WAVE':
- self.wave(box, ob, md)
+ self.wave(box, md)
- def armature(self, layout, ob, md):
+ def armature(self, layout, md):
layout.itemR(md, "object")
row = layout.row()
- row.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ row.itemR(md, "vertex_group")
row.itemR(md, "invert")
flow = layout.column_flow()
flow.itemR(md, "use_vertex_groups", text="Vertex Groups")
@@ -92,7 +92,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
flow.itemR(md, "quaternion")
flow.itemR(md, "multi_modifier")
- def array(self, layout, ob, md):
+ def array(self, layout, md):
layout.itemR(md, "fit_type")
if md.fit_type == 'FIXED_COUNT':
layout.itemR(md, "count")
@@ -141,7 +141,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "start_cap")
col.itemR(md, "end_cap")
- def bevel(self, layout, ob, md):
+ def bevel(self, layout, md):
row = layout.row()
row.itemR(md, "width")
row.itemR(md, "only_vertices")
@@ -156,11 +156,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
row = layout.row()
row.itemR(md, "edge_weight_method", expand=True)
- def boolean(self, layout, ob, md):
+ def boolean(self, layout, md):
layout.itemR(md, "operation")
layout.itemR(md, "object")
- def build(self, layout, ob, md):
+ def build(self, layout, md):
split = layout.split()
col = split.column()
@@ -175,7 +175,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
- def cast(self, layout, ob, md):
+ def cast(self, layout, md):
layout.itemR(md, "cast_type")
col = layout.column_flow()
col.itemR(md, "x")
@@ -184,26 +184,26 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "factor")
col.itemR(md, "radius")
col.itemR(md, "size")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
#Missing: "OB" and "From Radius"
- def cloth(self, layout, ob, md):
+ def cloth(self, layout, md):
layout.itemL(text="See Cloth panel.")
- def collision(self, layout, ob, md):
+ def collision(self, layout, md):
layout.itemL(text="See Collision panel.")
- def curve(self, layout, ob, md):
+ def curve(self, layout, md):
layout.itemR(md, "object")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "deform_axis")
- def decimate(self, layout, ob, md):
+ def decimate(self, layout, md):
layout.itemR(md, "ratio")
layout.itemR(md, "face_count")
- def displace(self, layout, ob, md):
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ def displace(self, layout, md):
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "texture")
layout.itemR(md, "midlevel")
layout.itemR(md, "strength")
@@ -211,10 +211,10 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "texture_coordinates")
if md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinate_object", text="Object")
- if md.texture_coordinates == 'UV' and ob.type == 'MESH':
- layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
+ if md.texture_coordinates == 'UV':
+ layout.itemR(md, "uv_layer")
- def edgesplit(self, layout, ob, md):
+ def edgesplit(self, layout, md):
split = layout.split()
col = split.column()
@@ -225,8 +225,8 @@ class DATA_PT_modifiers(DataButtonsPanel):
col = split.column()
col.itemR(md, "use_sharp", text="Sharp Edges")
- def explode(self, layout, ob, md):
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ def explode(self, layout, md):
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "protect")
layout.itemR(md, "split_edges")
layout.itemR(md, "unborn")
@@ -234,31 +234,31 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "dead")
# Missing: "Refresh" and "Clear Vertex Group" ?
- def fluid(self, layout, ob, md):
+ def fluid(self, layout, md):
layout.itemL(text="See Fluidsim panel.")
- def hook(self, layout, ob, md):
+ def hook(self, layout, md):
layout.itemR(md, "falloff")
layout.itemR(md, "force", slider=True)
layout.itemR(md, "object")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
# Missing: "Reset" and "Recenter"
- def lattice(self, layout, ob, md):
+ def lattice(self, layout, md):
layout.itemR(md, "object")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
- def mask(self, layout, ob, md):
+ def mask(self, layout, md):
layout.itemR(md, "mode")
if md.mode == 'ARMATURE':
layout.itemR(md, "armature")
if md.mode == 'VERTEX_GROUP':
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "inverse")
- def mesh_deform(self, layout, ob, md):
+ def mesh_deform(self, layout, md):
layout.itemR(md, "object")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "invert")
layout.itemS()
@@ -267,7 +267,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
row.itemR(md, "precision")
row.itemR(md, "dynamic")
- def mirror(self, layout, ob, md):
+ def mirror(self, layout, md):
layout.itemR(md, "merge_limit")
split = layout.split()
@@ -285,12 +285,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "mirror_object")
- def multires(self, layout, ob, md):
+ def multires(self, layout, md):
layout.itemR(md, "subdivision_type")
layout.itemO("OBJECT_OT_multires_subdivide", text="Subdivide")
layout.itemR(md, "level")
- def particleinstance(self, layout, ob, md):
+ def particleinstance(self, layout, md):
layout.itemR(md, "object")
layout.itemR(md, "particle_system_number")
@@ -302,12 +302,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "alive")
col.itemR(md, "dead")
- def particlesystem(self, layout, ob, md):
+ def particlesystem(self, layout, md):
layout.itemL(text="See Particle panel.")
- def shrinkwrap(self, layout, ob, md):
+ def shrinkwrap(self, layout, md):
layout.itemR(md, "target")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "offset")
layout.itemR(md, "subsurf_levels")
layout.itemR(md, "mode")
@@ -329,9 +329,9 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "keep_above_surface")
# To-Do: Validate if structs
- def simpledeform(self, layout, ob, md):
+ def simpledeform(self, layout, md):
layout.itemR(md, "mode")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "origin")
layout.itemR(md, "relative")
layout.itemR(md, "factor")
@@ -340,7 +340,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "lock_x_axis")
layout.itemR(md, "lock_y_axis")
- def smooth(self, layout, ob, md):
+ def smooth(self, layout, md):
split = layout.split()
sub = split.column()
sub.itemR(md, "x")
@@ -350,12 +350,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
sub.itemR(md, "factor")
sub.itemR(md, "repeat")
- layout.template_pointer(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
- def softbody(self, layout, ob, md):
+ def softbody(self, layout, md):
layout.itemL(text="See Softbody panel.")
- def subsurf(self, layout, ob, md):
+ def subsurf(self, layout, md):
layout.itemR(md, "subdivision_type")
col = layout.column_flow()
col.itemR(md, "levels", text="Preview")
@@ -363,17 +363,16 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "optimal_draw", text="Optimal Display")
col.itemR(md, "subsurf_uv")
- def uvproject(self, layout, ob, md):
- if ob.type == 'MESH':
- layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
- layout.itemR(md, "projectors")
- layout.itemR(md, "image")
- layout.itemR(md, "horizontal_aspect_ratio")
- layout.itemR(md, "vertical_aspect_ratio")
- layout.itemR(md, "override_image")
- #"Projectors" don't work.
-
- def wave(self, layout, ob, md):
+ def uvproject(self, layout, md):
+ layout.itemR(md, "uv_layer")
+ layout.itemR(md, "projectors")
+ layout.itemR(md, "image")
+ layout.itemR(md, "horizontal_aspect_ratio")
+ layout.itemR(md, "vertical_aspect_ratio")
+ layout.itemR(md, "override_image")
+ #"Projectors" don't work.
+
+ def wave(self, layout, md):
split = layout.split()
sub = split.column()
@@ -399,11 +398,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "start_position_y")
layout.itemR(md, "start_position_object")
- layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+ layout.itemR(md, "vertex_group")
layout.itemR(md, "texture")
layout.itemR(md, "texture_coordinates")
- if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
- layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
+ if md.texture_coordinates == 'MAP_UV':
+ layout.itemR(md, "uv_layer")
if md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinates_object")
@@ -413,4 +412,4 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "width", slider=True)
col.itemR(md, "narrowness", slider=True)
-bpy.types.register(DATA_PT_modifiers)
+bpy.types.register(DATA_PT_modifiers) \ No newline at end of file
diff --git a/release/ui/buttons_data_text.py b/release/ui/buttons_data_text.py
index 5f4cdd3f838..bce16e78a40 100644
--- a/release/ui/buttons_data_text.py
+++ b/release/ui/buttons_data_text.py
@@ -27,10 +27,10 @@ class DATA_PT_shape_text(DataButtonsPanel):
split = layout.split(percentage=0.65)
if ob:
- split.template_ID(ob, "data")
+ split.template_ID(context, ob, "data")
split.itemS()
elif curve:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if curve:
diff --git a/release/ui/buttons_material.py b/release/ui/buttons_material.py
index 8b0ef82b628..124fba83608 100644
--- a/release/ui/buttons_material.py
+++ b/release/ui/buttons_material.py
@@ -40,10 +40,10 @@ class MATERIAL_PT_material(MaterialButtonsPanel):
split = layout.split(percentage=0.65)
if ob and slot:
- split.template_ID(slot, "material", new="MATERIAL_OT_new")
+ split.template_ID(context, slot, "material", new="MATERIAL_OT_new")
split.itemR(ob, "active_material_index", text="Active")
elif mat:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
if mat:
diff --git a/release/ui/buttons_object_constraint.py b/release/ui/buttons_object_constraint.py
index f2b0b986ab9..f4507f9149d 100644
--- a/release/ui/buttons_object_constraint.py
+++ b/release/ui/buttons_object_constraint.py
@@ -67,7 +67,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row.itemR(con, "target_space", text="")
if target and owner:
- row.itemL(icon="ICON_ARROW_LEFTRIGHT")
+ row.itemL(icon=8) # XXX
if owner:
row.itemR(con, "owner_space", text="")
@@ -77,14 +77,13 @@ class ConstraintButtonsPanel(bpy.types.Panel):
if con.target and subtargets:
if con.target.type == "ARMATURE":
- layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone")
+ layout.itemR(con, "subtarget", text="Bone") # XXX autocomplete
- if con.type == 'COPY_LOCATION':
- row = layout.row()
- row.itemL(text="Head/Tail:")
- row.itemR(con, "head_tail", text="")
+ row = layout.row()
+ row.itemL(text="Head/Tail:")
+ row.itemR(con, "head_tail", text="")
elif con.target.type in ("MESH", "LATTICE"):
- layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
+ layout.itemR(con, "subtarget", text="Vertex Group") # XXX autocomplete
def child_of(self, layout, con):
self.target_template(layout, con)
@@ -529,23 +528,23 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel):
class BONE_PT_constraints(ConstraintButtonsPanel):
__idname__ = "BONE_PT_constraints"
__label__ = "Bone Constraints"
- __context__ = "bone"
+ __context__ = "constraint"
def poll(self, context):
ob = context.object
- return (ob and ob.type == "ARMATURE" and context.bone)
+ return (ob and ob.type == "ARMATURE")
def draw(self, context):
ob = context.object
- pchan = ob.pose.pose_channels[context.bone.name]
+ pchan = ob.pose.pose_channels[0] # XXX
layout = self.layout
- row = layout.row()
- row.item_menu_enumO("OBJECT_OT_constraint_add", "type")
- row.itemL();
+ #row = layout.row()
+ #row.item_menu_enumO("BONE_OT_constraint_add", "type")
+ #row.itemL();
for con in pchan.constraints:
self.draw_constraint(con)
bpy.types.register(OBJECT_PT_constraints)
-bpy.types.register(BONE_PT_constraints)
+bpy.types.register(BONE_PT_constraints) \ No newline at end of file
diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py
index e51df6ef7fd..571cafb709d 100644
--- a/release/ui/buttons_particle.py
+++ b/release/ui/buttons_particle.py
@@ -7,7 +7,6 @@ def particle_panel_enabled(psys):
def particle_panel_poll(context):
psys = context.particle_system
if psys==None: return False
- if psys.settings==None: return False
return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
class ParticleButtonsPanel(bpy.types.Panel):
@@ -30,51 +29,75 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
ob = context.object
psys = context.particle_system
- if ob:
- row = layout.row()
+ split = layout.split(percentage=0.65)
- row.template_list(ob, "particle_systems", "active_particle_system_index")
+ if psys:
+ split.template_ID(context, psys, "settings")
- col = row.column(align=True)
- col.itemO("OBJECT_OT_particle_system_slot_add", icon="ICON_ZOOMIN", text="")
- col.itemO("OBJECT_OT_particle_system_slot_remove", icon="ICON_ZOOMOUT", text="")
+ #if ob:
+ # split.itemR(ob, "active_particle_system_index", text="Active")
if psys:
- split = layout.split(percentage=0.65)
+ #row = layout.row()
+ #row.itemL(text="Particle system datablock")
+ #row.itemL(text="Viewport")
+ #row.itemL(text="Render")
- split.template_ID(psys, "settings", new="PARTICLE_OT_new")
+ part = psys.settings
+ ptype = psys.settings.type
+
+ if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
+ layout.itemL(text="No settings for fluid particles")
+ return
+
+ row = layout.row()
+ row.enabled = particle_panel_enabled(psys)
+ row.itemR(part, "type")
+ row.itemR(psys, "seed")
+ row = layout.row()
+ if part.type=='HAIR':
+ if psys.editable==True:
+ row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
+ else:
+ row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
+ subrow = row.row()
+ subrow.enabled = particle_panel_enabled(psys)
+ subrow.itemR(part, "hair_step")
+ elif part.type=='REACTOR':
+ row.itemR(psys, "reactor_target_object")
+ row.itemR(psys, "reactor_target_particle_system", text="Particle System")
+
+ if psys:
#row = layout.row()
+ #row.itemL(text="Particle system datablock")
#row.itemL(text="Viewport")
#row.itemL(text="Render")
part = psys.settings
+ ptype = psys.settings.type
- if part:
- ptype = psys.settings.type
- if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
- layout.itemL(text="No settings for fluid particles")
- return
-
- split = layout.split(percentage=0.65)
-
- split.enabled = particle_panel_enabled(psys)
- split.itemR(part, "type")
- split.itemR(psys, "seed")
-
- split = layout.split(percentage=0.65)
- if part.type=='HAIR':
- if psys.editable==True:
- split.itemO("PARTICLE_OT_editable_set", text="Free Edit")
- else:
- split.itemO("PARTICLE_OT_editable_set", text="Make Editable")
- row = split.row()
- row.enabled = particle_panel_enabled(psys)
- row.itemR(part, "hair_step")
- elif part.type=='REACTOR':
- split.enabled = particle_panel_enabled(psys)
- split.itemR(psys, "reactor_target_object")
- split.itemR(psys, "reactor_target_particle_system", text="Particle System")
+ if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
+ layout.itemL(text="No settings for fluid particles")
+ return
+
+ row = layout.row()
+ row.enabled = particle_panel_enabled(psys)
+ row.itemR(part, "type", expand=True)
+
+
+ row = layout.row()
+ if part.type=='HAIR':
+ if psys.editable==True:
+ row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
+ else:
+ row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
+ subrow = row.row()
+ subrow.enabled = particle_panel_enabled(psys)
+ subrow.itemR(part, "hair_step")
+ elif part.type=='REACTOR':
+ row.itemR(psys, "reactor_target_object")
+ row.itemR(psys, "reactor_target_particle_system", text="Particle System")
class PARTICLE_PT_emission(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_emission"
@@ -89,7 +112,9 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
layout.enabled = particle_panel_enabled(psys)
row = layout.row()
+ #col.itemL(text="TODO: Rate instead of amount")
row.itemR(part, "amount")
+ row.itemR(psys, "seed")
split = layout.split()
@@ -125,12 +150,10 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
class PARTICLE_PT_cache(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_cache"
__label__ = "Cache"
- __default_closed__ = True
def poll(self, context):
psys = context.particle_system
if psys==None: return False
- if psys.settings==None: return False
return psys.settings.type in ('EMITTER', 'REACTOR')
def draw(self, context):
@@ -140,42 +163,15 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
part = psys.settings
cache = psys.point_cache
+ #if cache.baked==True:
+ #layout.itemO("PARTICLE_OT_free_bake", text="BAKE")
+ #else:
row = layout.row()
- row.itemR(cache, "name")
-
- row = layout.row()
-
- if cache.baked == True:
- row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
- else:
- row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
-
- subrow = row.row()
- subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
- subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
-
- row = layout.row()
- row.enabled = particle_panel_enabled(psys)
- row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
- row.itemR(cache, "step");
-
- row = layout.row()
- row.enabled = particle_panel_enabled(psys)
- row.itemR(cache, "quick_cache")
- row.itemR(cache, "disk_cache")
-
- layout.itemL(text=cache.info)
-
- layout.itemS()
-
- row = layout.row()
- row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
- row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
- layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
-
- # for particles these are figured out automatically
- #row.itemR(cache, "start_frame")
- #row.itemR(cache, "end_frame")
+ #row.itemO("PARTICLE_OT_bake", text="BAKE")
+ row.itemR(cache, "start_frame")
+ row.itemR(cache, "end_frame")
+
+ #layout.row().itemL(text="No simulation frames in disk cache.")
class PARTICLE_PT_initial(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_initial"
@@ -188,6 +184,8 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
part = psys.settings
layout.enabled = particle_panel_enabled(psys)
+
+ #layout.row().itemL(text="")
layout.row().itemL(text="Direction:")
@@ -298,10 +296,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
__label__ = "Render"
def poll(self, context):
- psys = context.particle_system
- if psys==None: return False
- if psys.settings==None: return False
- return True;
+ return (context.particle_system != None)
def draw(self, context):
layout = self.layout
@@ -309,9 +304,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
psys = context.particle_system
part = psys.settings
- row = layout.row()
- row.itemR(part, "material")
- row.itemR(psys, "parent");
+ layout.itemR(part, "material")
split = layout.split()
@@ -369,14 +362,27 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
row = layout.row()
col = row.column()
+
+# subrow = col.row()
+# subrow.active = part.render_strand == False
+# subrow.itemR(part, "render_adaptive")
+# col = row.column(align=True)
+# subrow = col.row()
+# subrow.active = part.render_adaptive or part.render_strand == True
+# subrow.itemR(part, "adaptive_angle")
+# subrow = col.row()
+# subrow.active = part.render_adaptive == True and part.render_strand == False
+# subrow.itemR(part, "adaptive_pix")
+
if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
layout.itemR(part, "enable_simplify")
if part.enable_simplify==True:
- row = layout.row()
+ box = layout.box()
+ row = box.row()
row.itemR(part, "simplify_refsize")
row.itemR(part, "simplify_rate")
row.itemR(part, "simplify_transition")
- row = layout.row()
+ row = box.row()
row.itemR(part, "viewport")
subrow = row.row()
subrow.active = part.viewport==True
@@ -432,13 +438,9 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
class PARTICLE_PT_draw(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_draw"
__label__ = "Display"
- __default_closed__ = True
def poll(self, context):
- psys = context.particle_system
- if psys==None: return False
- if psys.settings==None: return False
- return True;
+ return (context.particle_system != None)
def draw(self, context):
layout = self.layout
@@ -488,7 +490,6 @@ class PARTICLE_PT_draw(ParticleButtonsPanel):
class PARTICLE_PT_children(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_children"
__label__ = "Children"
- __default_closed__ = True
def draw(self, context):
layout = self.layout
@@ -556,7 +557,6 @@ class PARTICLE_PT_children(ParticleButtonsPanel):
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_vertexgroups"
__label__ = "Vertexgroups"
- __default_closed__ = True
def draw(self, context):
layout = self.layout
diff --git a/release/ui/buttons_physic_cloth.py b/release/ui/buttons_physic_cloth.py
index a06c644322a..bd65392ad63 100644
--- a/release/ui/buttons_physic_cloth.py
+++ b/release/ui/buttons_physic_cloth.py
@@ -43,54 +43,7 @@ class Physic_PT_cloth(PhysicButtonsPanel):
col.itemR(cloth, "goal_spring", text="Stiffness")
col.itemR(cloth, "goal_friction", text="Friction")
"""
-
-class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
- __idname__= "PHYSICS_PT_cloth_cache"
- __label__ = "Cache"
- __default_closed__ = True
-
- def draw(self, context):
- layout = self.layout
-
- cache = context.cloth.point_cache
-
- row = layout.row()
- row.itemR(cache, "name")
-
- row = layout.row()
- row.itemR(cache, "start_frame")
- row.itemR(cache, "end_frame")
-
- row = layout.row()
-
- if cache.baked == True:
- row.itemO("PTCACHE_OT_free_bake_cloth", text="Free Bake")
- else:
- row.item_booleanO("PTCACHE_OT_cache_cloth", "bake", True, text="Bake")
-
- subrow = row.row()
- subrow.enabled = cache.frames_skipped or cache.outdated
- subrow.itemO("PTCACHE_OT_cache_cloth", text="Calculate to Current Frame")
-
- row = layout.row()
- #row.enabled = particle_panel_enabled(psys)
- row.itemO("PTCACHE_OT_bake_from_cloth_cache", text="Current Cache to Bake")
- row.itemR(cache, "step");
- row = layout.row()
- #row.enabled = particle_panel_enabled(psys)
- row.itemR(cache, "quick_cache")
- row.itemR(cache, "disk_cache")
-
- layout.itemL(text=cache.info)
-
- layout.itemS()
-
- row = layout.row()
- row.itemO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
- row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
- layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
-
class Physic_PT_cloth_collision(PhysicButtonsPanel):
__idname__ = "Physic_PT_clothcollision"
__label__ = "Cloth Collision"
@@ -149,6 +102,5 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
sub.itemR(cloth, "bending_stiffness_max", text="Max")
bpy.types.register(Physic_PT_cloth)
-bpy.types.register(PHYSICS_PT_cloth_cache)
bpy.types.register(Physic_PT_cloth_collision)
bpy.types.register(Physic_PT_cloth_stiffness)
diff --git a/release/ui/buttons_texture.py b/release/ui/buttons_texture.py
index 31908d5ec9c..de166cef796 100644
--- a/release/ui/buttons_texture.py
+++ b/release/ui/buttons_texture.py
@@ -43,7 +43,7 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
if ma or la or wo:
if slot:
- split.template_ID(slot, "texture", new="TEXTURE_OT_new")
+ split.template_ID(context, slot, "texture", new="TEXTURE_OT_new")
else:
split.itemS()
@@ -54,7 +54,7 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
elif wo:
split.itemR(wo, "active_texture_index", text="Active")
elif tex:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
layout.itemS()
diff --git a/release/ui/buttons_world.py b/release/ui/buttons_world.py
index 39b5eca04ff..d9516cb7900 100644
--- a/release/ui/buttons_world.py
+++ b/release/ui/buttons_world.py
@@ -37,9 +37,9 @@ class WORLD_PT_world(WorldButtonsPanel):
split = layout.split(percentage=0.65)
if scene:
- split.template_ID(scene, "world", new="WORLD_OT_new")
+ split.template_ID(context, scene, "world", new="WORLD_OT_new")
elif world:
- split.template_ID(space, "pin_id")
+ split.template_ID(context, space, "pin_id")
split.itemS()
diff --git a/release/ui/space_image.py b/release/ui/space_image.py
index 63ca316efe7..3623b914942 100644
--- a/release/ui/space_image.py
+++ b/release/ui/space_image.py
@@ -9,7 +9,6 @@ class IMAGE_MT_view(bpy.types.Menu):
layout = self.layout
sima = context.space_data
uv = sima.uv_editor
- settings = context.scene.tool_settings
show_uvedit = sima.show_uvedit
@@ -18,8 +17,8 @@ class IMAGE_MT_view(bpy.types.Menu):
layout.itemS()
layout.itemR(sima, "update_automatically")
- if show_uvedit:
- layout.itemR(settings, "uv_local_view") # Numpad /
+ # XXX if show_uvedit:
+ # XXX layout.itemR(uv, "local_view") # "UV Local View", Numpad /
layout.itemS()
@@ -157,7 +156,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
layout = self.layout
sima = context.space_data
uv = sima.uv_editor
- settings = context.scene.tool_settings
+ scene = context.scene
layout.itemR(uv, "snap_to_pixels")
layout.itemR(uv, "constrain_to_image_bounds")
@@ -178,18 +177,18 @@ class IMAGE_MT_uvs(bpy.types.Menu):
layout.itemS()
- layout.itemM("IMAGE_MT_uvs_transform")
- layout.itemM("IMAGE_MT_uvs_mirror")
- layout.itemM("IMAGE_MT_uvs_weldalign")
+ layout.itemM(context, "IMAGE_MT_uvs_transform")
+ layout.itemM(context, "IMAGE_MT_uvs_mirror")
+ layout.itemM(context, "IMAGE_MT_uvs_weldalign")
layout.itemS()
- layout.itemR(settings, "proportional_editing")
- layout.item_menu_enumR(settings, "proportional_editing_falloff")
+ # XXX layout.itemR(scene, "proportional_editing")
+ layout.item_menu_enumR(scene, "proportional_editing_falloff")
layout.itemS()
- layout.itemM("IMAGE_MT_uvs_showhide")
+ layout.itemM(context, "IMAGE_MT_uvs_showhide")
class IMAGE_HT_header(bpy.types.Header):
__space_type__ = "IMAGE_EDITOR"
@@ -197,31 +196,29 @@ class IMAGE_HT_header(bpy.types.Header):
def draw(self, context):
sima = context.space_data
ima = sima.image
- iuser = sima.image_user
layout = self.layout
- settings = context.scene.tool_settings
show_render = sima.show_render
show_paint = sima.show_paint
show_uvedit = sima.show_uvedit
- layout.template_header()
+ layout.template_header(context)
# menus
if context.area.show_menus:
row = layout.row()
- row.itemM("IMAGE_MT_view")
+ row.itemM(context, "IMAGE_MT_view")
if show_uvedit:
- row.itemM("IMAGE_MT_select")
+ row.itemM(context, "IMAGE_MT_select")
# XXX menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image";
- row.itemM("IMAGE_MT_image")
+ row.itemM(context, "IMAGE_MT_image")
if show_uvedit:
- row.itemM("IMAGE_MT_uvs")
+ row.itemM(context, "IMAGE_MT_uvs")
- layout.template_ID(sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
+ layout.template_ID(context, sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
"""
/* image select */
@@ -253,33 +250,108 @@ class IMAGE_HT_header(bpy.types.Header):
# uv editing
if show_uvedit:
- uvedit = sima.uv_editor
+ pass
+
+ """
+ /* uv editing */
+ if(show_uvedit) {
+ /* pivot */
+ uiDefIconTextButS(block, ICONTEXTROW, B_NOP, ICON_ROTATE,
+ "Pivot: %t|Bounding Box Center %x0|Median Point %x3|2D Cursor %x1",
+ xco,yco,XIC+10,YIC, &ar->v2d.around, 0, 3.0, 0, 0,
+ "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period)");
+ xco+= XIC + 18;
+
+ /* selection modes */
+ uiDefIconButBitS(block, TOG, UV_SYNC_SELECTION, B_REDR, ICON_EDIT, xco,yco,XIC,YIC, &scene->toolsettings->uv_flag, 0, 0, 0, 0, "Sync UV and Mesh Selection");
+ xco+= XIC+8;
- layout.itemS()
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+
+ uiBlockEndAlign(block);
+ }
+ else {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_VERTEX, 0, 0, "Vertex select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_EDGE, 0, 0, "Edge select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_FACE, 0, 0, "Face select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_LINKEDSEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_ISLAND, 0, 0, "Island select mode");
+
+ uiBlockEndAlign(block);
+
+ /* would use these if const's could go in strings
+ * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */
+ but = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC,
+ "Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2",
+ xco+=XIC+10,yco,XIC+10,YIC, &(sima->sticky), 0, 3.0, 0, 0,
+ "Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)");
+ }
+
+ xco+= XIC + 16;
+
+ /* snap options, identical to options in 3d view header */
+ uiBlockBeginAlign(block);
+
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
+ xco+= XIC;
+ uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
+ xco+= 70;
+ }
+ else {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");
+ xco+= XIC;
+ }
- layout.itemR(uvedit, "pivot", text="")
- layout.itemR(settings, "uv_sync_selection", text="")
+ uiBlockEndAlign(block);
+ xco+= 8;
- if settings.uv_sync_selection:
- layout.itemR(settings, "mesh_selection_mode", text="", expand=True)
- else:
- layout.itemR(settings, "uv_selection_mode", text="", expand=True)
- layout.itemR(uvedit, "sticky_selection_mode", text="")
- pass
+ /* uv layers */
+ {
+ Object *obedit= CTX_data_edit_object(C);
+ char menustr[34*MAX_MTFACE];
+ static int act;
+
+ image_menu_uvlayers(obedit, menustr, &act);
- row = layout.row(align=True)
- row.itemR(settings, "snap", text="")
- if settings.snap:
- row.itemR(settings, "snap_mode", text="")
+ but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing.");
+ // uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL);
+
+ xco+= 85;
+ }
- """
- mesh = context.edit_object.data
- row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_layers")
- """
+ xco+= 8;
+ }
+ """
if ima:
- # layers
- layout.template_image_layers(ima, iuser)
+ """
+ RenderResult *rr;
+
+ /* render layers and passes */
+ rr= BKE_image_get_renderresult(scene, ima);
+ if(rr) {
+ uiBlockBeginAlign(block);
+#if 0
+ uiblock_layer_pass_buttons(block, rr, &sima->iuser, B_REDR, xco, 0, 160);
+#endif
+ uiBlockEndAlign(block);
+ xco+= 166;
+ }
+ """
# painting
layout.itemR(sima, "image_painting", text="")
@@ -301,10 +373,6 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
__region_type__ = "UI"
__label__ = "Game Properties"
- def poll(self, context):
- sima = context.space_data
- return (sima and sima.image)
-
def draw(self, context):
sima = context.space_data
layout = self.layout
@@ -314,83 +382,446 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
if ima:
split = layout.split()
- col = split.column()
-
- subcol = col.column(align=True)
- subcol.itemR(ima, "clamp_x")
- subcol.itemR(ima, "clamp_y")
-
- col.itemR(ima, "mapping", expand=True)
- col.itemR(ima, "tiles")
-
- col = split.column()
-
- subcol = col.column(align=True)
- subcol.itemR(ima, "animated")
+ col = split.column(align=True)
+ col.itemR(ima, "animated")
- subcol = subcol.column()
+ subcol = col.column()
subcol.itemR(ima, "animation_start", text="Start")
subcol.itemR(ima, "animation_end", text="End")
subcol.itemR(ima, "animation_speed", text="Speed")
subcol.active = ima.animated
+ col = split.column()
+ col.itemR(ima, "tiles")
+
subrow = col.row(align=True)
subrow.itemR(ima, "tiles_x", text="X")
subrow.itemR(ima, "tiles_y", text="Y")
- subrow.active = ima.tiles or ima.animated
+ subrow.active = ima.tiles
+
+ col.itemS()
+ col.itemR(ima, "clamp_x")
+ col.itemR(ima, "clamp_y")
+
+ col.itemR(ima, "mapping", expand=True)
+
+bpy.types.register(IMAGE_MT_view)
+bpy.types.register(IMAGE_MT_select)
+bpy.types.register(IMAGE_MT_image)
+bpy.types.register(IMAGE_MT_uvs_showhide)
+bpy.types.register(IMAGE_MT_uvs_transform)
+bpy.types.register(IMAGE_MT_uvs_mirror)
+bpy.types.register(IMAGE_MT_uvs_weldalign)
+bpy.types.register(IMAGE_MT_uvs)
+bpy.types.register(IMAGE_HT_header)
+bpy.types.register(IMAGE_PT_game_properties)
+
-class IMAGE_PT_view_properties(bpy.types.Panel):
+import bpy
+
+class IMAGE_MT_view(bpy.types.Menu):
__space_type__ = "IMAGE_EDITOR"
- __region_type__ = "UI"
- __label__ = "View Properties"
+ __label__ = "View"
def draw(self, context):
+ layout = self.layout
sima = context.space_data
+ uv = sima.uv_editor
+
+ show_uvedit = sima.show_uvedit
+
+ layout.itemO("IMAGE_OT_properties") # icon
+
+ layout.itemS()
+
+ layout.itemR(sima, "update_automatically")
+ # XXX if show_uvedit:
+ # XXX layout.itemR(uv, "local_view") # "UV Local View", Numpad /
+
+ layout.itemS()
+
+ layout.itemO("IMAGE_OT_view_zoom_in")
+ layout.itemO("IMAGE_OT_view_zoom_out")
+
+ layout.itemS()
+
+ ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]];
+
+ for a, b in ratios:
+ text = "Zoom %d:%d" % (a, b)
+ layout.item_floatO("IMAGE_OT_view_zoom_ratio", "ratio", a/b, text=text)
+
+ layout.itemS()
+
+ if show_uvedit:
+ layout.itemO("IMAGE_OT_view_selected")
+
+ layout.itemO("IMAGE_OT_view_all")
+ layout.itemO("SCREEN_OT_screen_full_area")
+
+class IMAGE_MT_select(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "Select"
+
+ def draw(self, context):
layout = self.layout
+ layout.itemO("UV_OT_select_border")
+ layout.item_booleanO("UV_OT_select_border", "pinned", True)
+
+ layout.itemS()
+
+ layout.itemO("UV_OT_select_all_toggle")
+ layout.itemO("UV_OT_select_invert")
+ layout.itemO("UV_OT_unlink_selection")
+
+ layout.itemS()
+
+ layout.itemO("UV_OT_select_pinned")
+ layout.itemO("UV_OT_select_linked")
+
+class IMAGE_MT_image(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "Image"
+
+ def draw(self, context):
+ layout = self.layout
+ sima = context.space_data
ima = sima.image
- show_uvedit = sima.show_uvedit
- uvedit = sima.uv_editor
- split = layout.split()
+ layout.itemO("IMAGE_OT_new")
+ layout.itemO("IMAGE_OT_open")
+
+ show_render = sima.show_render
- col = split.column()
if ima:
- col.itemR(ima, "display_aspect")
+ if show_render:
+ layout.itemO("IMAGE_OT_replace")
+ layout.itemO("IMAGE_OT_reload")
- col = split.column()
- col.itemR(sima, "draw_repeated", text="Repeat")
- if show_uvedit:
- col.itemR(uvedit, "normalized_coordinates")
+ layout.itemO("IMAGE_OT_save")
+ layout.itemO("IMAGE_OT_save_as")
- if show_uvedit:
- col = layout.column()
- row = col.row()
- row.itemR(uvedit, "edge_draw_type", expand=True)
- row = col.row()
- row.itemR(uvedit, "draw_smooth_edges", text="Smooth")
- row.itemR(uvedit, "draw_modified_edges", text="Modified")
-
- row = col.row()
- row.itemR(uvedit, "draw_stretch", text="Stretch")
- row.itemR(uvedit, "draw_stretch_type", text="")
- #col.itemR(uvedit, "draw_edges")
- #col.itemR(uvedit, "draw_faces")
-
-class IMAGE_PT_curves(bpy.types.Panel):
+ if ima.source == "SEQUENCE":
+ layout.itemO("IMAGE_OT_save_sequence")
+
+ if not show_render:
+ layout.itemS()
+
+ if ima.packed_file:
+ layout.itemO("IMAGE_OT_unpack")
+ else:
+ layout.itemO("IMAGE_OT_pack")
+
+ # only for dirty && specific image types : XXX poll?
+ #if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+ if False:
+ if ima.source in ("FILE", "GENERATED") and ima.type != "MULTILAYER":
+ layout.item_booleanO("IMAGE_OT_pack", "as_png", True, text="Pack As PNG")
+
+ layout.itemS()
+
+ layout.itemR(sima, "image_painting")
+
+class IMAGE_MT_uvs_showhide(bpy.types.Menu):
__space_type__ = "IMAGE_EDITOR"
- __region_type__ = "UI"
- __label__ = "Curves"
+ __label__ = "Show/Hide Faces"
- def poll(self, context):
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("UV_OT_reveal")
+ layout.itemO("UV_OT_hide")
+ layout.item_booleanO("UV_OT_hide", "unselected", True)
+
+class IMAGE_MT_uvs_transform(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "Transform"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.item_enumO("TFM_OT_transform", "mode", "TRANSLATION")
+ layout.item_enumO("TFM_OT_transform", "mode", "ROTATION")
+ layout.item_enumO("TFM_OT_transform", "mode", "RESIZE")
+
+class IMAGE_MT_uvs_mirror(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "Mirror"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_X") # "X Axis", M,
+ layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_Y") # "Y Axis", M,
+
+class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "Weld/Align"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("UV_OT_weld") # W, 1
+ layout.items_enumO("UV_OT_align", "axis") # W, 2/3/4
+
+
+class IMAGE_MT_uvs(bpy.types.Menu):
+ __space_type__ = "IMAGE_EDITOR"
+ __label__ = "UVs"
+
+ def draw(self, context):
+ layout = self.layout
sima = context.space_data
- return (sima and sima.image)
+ uv = sima.uv_editor
+ scene = context.scene
+
+ layout.itemR(uv, "snap_to_pixels")
+ layout.itemR(uv, "constrain_to_image_bounds")
+
+ layout.itemS()
+
+ layout.itemR(uv, "live_unwrap")
+ layout.itemO("UV_OT_unwrap")
+ layout.item_booleanO("UV_OT_pin", "clear", True, text="Unpin")
+ layout.itemO("UV_OT_pin")
+
+ layout.itemS()
+
+ layout.itemO("UV_OT_pack_islands")
+ layout.itemO("UV_OT_average_islands_scale")
+ layout.itemO("UV_OT_minimize_stretch")
+ layout.itemO("UV_OT_stitch")
+
+ layout.itemS()
+
+ layout.itemM(context, "IMAGE_MT_uvs_transform")
+ layout.itemM(context, "IMAGE_MT_uvs_mirror")
+ layout.itemM(context, "IMAGE_MT_uvs_weldalign")
+
+ layout.itemS()
+
+ # XXX layout.itemR(scene, "proportional_editing")
+ layout.item_menu_enumR(scene, "proportional_editing_falloff")
+
+ layout.itemS()
+
+ layout.itemM(context, "IMAGE_MT_uvs_showhide")
+
+class IMAGE_HT_header(bpy.types.Header):
+ __space_type__ = "IMAGE_EDITOR"
+
+ def draw(self, context):
+ sima = context.space_data
+ ima = sima.image
+ layout = self.layout
+
+ show_render = sima.show_render
+ show_paint = sima.show_paint
+ show_uvedit = sima.show_uvedit
+
+ layout.template_header(context)
+
+ # menus
+ if context.area.show_menus:
+ row = layout.row()
+ row.itemM(context, "IMAGE_MT_view")
+
+ if show_uvedit:
+ row.itemM(context, "IMAGE_MT_select")
+
+ # XXX menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image";
+ row.itemM(context, "IMAGE_MT_image")
+
+ if show_uvedit:
+ row.itemM(context, "IMAGE_MT_uvs")
+
+ layout.template_ID(context, sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
+
+ """
+ /* image select */
+
+ pinflag= (show_render)? 0: UI_ID_PIN;
+ xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)sima->image, ID_IM, &sima->pin, xco, yco,
+ sima_idpoin_handle, UI_ID_BROWSE|UI_ID_BROWSE_RENDER|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE|pinflag);
+ xco += 8;
+ """
+
+ """
+ if(ima && !ELEM3(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_VIEWER) && ima->ok) {
+ /* XXX this should not be a static var */
+ static int headerbuttons_packdummy;
+
+ headerbuttons_packdummy = 0;
+
+ if (ima->packedfile) {
+ headerbuttons_packdummy = 1;
+ }
+ if (ima->packedfile && ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+ uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMA_REPACK */, ICON_UGLYPACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Re-Pack this image as PNG");
+ else
+ uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMAPACKIMA */, ICON_PACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image");
+
+ xco+= XIC+8;
+ }
+ """
+
+ # uv editing
+ if show_uvedit:
+ pass
+
+ """
+ /* uv editing */
+ if(show_uvedit) {
+ /* pivot */
+ uiDefIconTextButS(block, ICONTEXTROW, B_NOP, ICON_ROTATE,
+ "Pivot: %t|Bounding Box Center %x0|Median Point %x3|2D Cursor %x1",
+ xco,yco,XIC+10,YIC, &ar->v2d.around, 0, 3.0, 0, 0,
+ "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period)");
+ xco+= XIC + 18;
+
+ /* selection modes */
+ uiDefIconButBitS(block, TOG, UV_SYNC_SELECTION, B_REDR, ICON_EDIT, xco,yco,XIC,YIC, &scene->toolsettings->uv_flag, 0, 0, 0, 0, "Sync UV and Mesh Selection");
+ xco+= XIC+8;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+
+ uiBlockEndAlign(block);
+ }
+ else {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_VERTEX, 0, 0, "Vertex select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_EDGE, 0, 0, "Edge select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_FACE, 0, 0, "Face select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_LINKEDSEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_ISLAND, 0, 0, "Island select mode");
+
+ uiBlockEndAlign(block);
+
+ /* would use these if const's could go in strings
+ * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */
+ but = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC,
+ "Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2",
+ xco+=XIC+10,yco,XIC+10,YIC, &(sima->sticky), 0, 3.0, 0, 0,
+ "Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)");
+ }
+
+ xco+= XIC + 16;
+
+ /* snap options, identical to options in 3d view header */
+ uiBlockBeginAlign(block);
+
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
+ xco+= XIC;
+ uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
+ xco+= 70;
+ }
+ else {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");
+ xco+= XIC;
+ }
+
+ uiBlockEndAlign(block);
+ xco+= 8;
+
+ /* uv layers */
+ {
+ Object *obedit= CTX_data_edit_object(C);
+ char menustr[34*MAX_MTFACE];
+ static int act;
+
+ image_menu_uvlayers(obedit, menustr, &act);
+
+ but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing.");
+ // uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL);
+
+ xco+= 85;
+ }
+
+ xco+= 8;
+ }
+ """
+
+ if ima:
+ """
+ RenderResult *rr;
+
+ /* render layers and passes */
+ rr= BKE_image_get_renderresult(scene, ima);
+ if(rr) {
+ uiBlockBeginAlign(block);
+#if 0
+ uiblock_layer_pass_buttons(block, rr, &sima->iuser, B_REDR, xco, 0, 160);
+#endif
+ uiBlockEndAlign(block);
+ xco+= 166;
+ }
+ """
+
+ # painting
+ layout.itemR(sima, "image_painting", text="")
+
+ # draw options
+ row = layout.row(align=True)
+ row.itemR(sima, "draw_channels", text="", expand=True)
+
+ row = layout.row(align=True)
+ if ima.type == "COMPOSITE":
+ row.itemO("IMAGE_OT_record_composite", icon="ICON_REC")
+ if ima.type == "COMPOSITE" and ima.source in ("MOVIE", "SEQUENCE"):
+ row.itemO("IMAGE_OT_play_composite", icon="ICON_PLAY")
+
+ layout.itemR(sima, "update_automatically", text="")
+
+class IMAGE_PT_game_properties(bpy.types.Panel):
+ __space_type__ = "IMAGE_EDITOR"
+ __region_type__ = "UI"
+ __label__ = "Game Properties"
def draw(self, context):
sima = context.space_data
layout = self.layout
- layout.template_curve_mapping(sima.curves)
+ ima = sima.image
+
+ if ima:
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.itemR(ima, "animated")
+
+ subcol = col.column()
+ subcol.itemR(ima, "animation_start", text="Start")
+ subcol.itemR(ima, "animation_end", text="End")
+ subcol.itemR(ima, "animation_speed", text="Speed")
+ subcol.active = ima.animated
+
+ col = split.column()
+ col.itemR(ima, "tiles")
+
+ subrow = col.row(align=True)
+ subrow.itemR(ima, "tiles_x", text="X")
+ subrow.itemR(ima, "tiles_y", text="Y")
+ subrow.active = ima.tiles
+
+ col.itemS()
+ col.itemR(ima, "clamp_x")
+ col.itemR(ima, "clamp_y")
+
+ col.itemR(ima, "mapping", expand=True)
bpy.types.register(IMAGE_MT_view)
bpy.types.register(IMAGE_MT_select)
@@ -402,6 +833,4 @@ bpy.types.register(IMAGE_MT_uvs_weldalign)
bpy.types.register(IMAGE_MT_uvs)
bpy.types.register(IMAGE_HT_header)
bpy.types.register(IMAGE_PT_game_properties)
-bpy.types.register(IMAGE_PT_view_properties)
-#bpy.types.register(IMAGE_PT_curves)
diff --git a/release/ui/space_logic.py b/release/ui/space_logic.py
index f862f6e2667..71d94c86bf3 100644
--- a/release/ui/space_logic.py
+++ b/release/ui/space_logic.py
@@ -5,10 +5,6 @@ class LOGIC_PT_physics(bpy.types.Panel):
__region_type__ = "UI"
__label__ = "Physics"
- def poll(self, context):
- ob = context.active_object
- return ob and ob.game
-
def draw(self, context):
layout = self.layout
ob = context.active_object
@@ -60,10 +56,6 @@ class LOGIC_PT_collision_bounds(bpy.types.Panel):
__space_type__ = "LOGIC_EDITOR"
__region_type__ = "UI"
__label__ = "Collision Bounds"
-
- def poll(self, context):
- ob = context.active_object
- return ob and ob.game
def draw_header(self, context):
layout = self.layout
diff --git a/release/ui/space_outliner.py b/release/ui/space_outliner.py
index 5a6ee5ea2aa..f039eb3f7c3 100644
--- a/release/ui/space_outliner.py
+++ b/release/ui/space_outliner.py
@@ -10,11 +10,11 @@ class OUTLINER_HT_header(bpy.types.Header):
sce = context.scene
layout = self.layout
- layout.template_header()
+ layout.template_header(context)
if context.area.show_menus:
row = layout.row(align=True)
- row.itemM("OUTLINER_MT_view")
+ row.itemM(context, "OUTLINER_MT_view")
row = layout.row()
row.itemR(so, "display_mode", text="")
diff --git a/release/ui/space_sequencer.py b/release/ui/space_sequencer.py
index b64e7d8e0c4..94858db81ad 100644
--- a/release/ui/space_sequencer.py
+++ b/release/ui/space_sequencer.py
@@ -15,21 +15,21 @@ class SEQUENCER_HT_header(bpy.types.Header):
st = context.space_data
layout = self.layout
- layout.template_header()
+ layout.template_header(context)
if context.area.show_menus:
row = layout.row()
- row.itemM("SEQUENCER_MT_view")
+ row.itemM(context, "SEQUENCER_MT_view")
row.itemR(st, "display_mode")
layout.itemS()
if st.display_mode == 'SEQUENCER':
- row.itemM("SEQUENCER_MT_select")
- row.itemM("SEQUENCER_MT_marker")
- row.itemM("SEQUENCER_MT_add")
- row.itemM("SEQUENCER_MT_strip")
+ row.itemM(context, "SEQUENCER_MT_select")
+ row.itemM(context, "SEQUENCER_MT_marker")
+ row.itemM(context, "SEQUENCER_MT_add")
+ row.itemM(context, "SEQUENCER_MT_strip")
layout.itemS()
row.itemO("SEQUENCER_OT_reload")
else:
@@ -151,7 +151,7 @@ class SEQUENCER_MT_add(bpy.types.Menu):
layout.itemO("SEQUENCER_OT_sound_strip_add", text="Sound (Ram)")
layout.item_booleanO("SEQUENCER_OT_sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY
- layout.itemM("SEQUENCER_MT_add_effect")
+ layout.itemM(context, "SEQUENCER_MT_add_effect")
class SEQUENCER_MT_add_effect(bpy.types.Menu):
diff --git a/release/ui/space_text.py b/release/ui/space_text.py
index 07e43f32054..42e5347ce6a 100644
--- a/release/ui/space_text.py
+++ b/release/ui/space_text.py
@@ -1,6 +1,10 @@
import bpy
+# temporary
+ICON_TEXT = 120
+ICON_HELP = 1
+
class TEXT_HT_header(bpy.types.Header):
__space_type__ = "TEXT_EDITOR"
__idname__ = "TEXT_HT_header"
@@ -10,14 +14,14 @@ class TEXT_HT_header(bpy.types.Header):
text = st.text
layout = self.layout
- layout.template_header()
+ layout.template_header(context)
if context.area.show_menus:
row = layout.row()
- row.itemM("TEXT_MT_text")
+ row.itemM(context, "TEXT_MT_text")
if text:
- row.itemM("TEXT_MT_edit")
- row.itemM("TEXT_MT_format")
+ row.itemM(context, "TEXT_MT_edit")
+ row.itemM(context, "TEXT_MT_format")
if text and text.modified:
row = layout.row()
@@ -29,7 +33,7 @@ class TEXT_HT_header(bpy.types.Header):
row.itemR(st, "word_wrap", text="")
row.itemR(st, "syntax_highlight", text="")
- layout.template_ID(st, "text", new="TEXT_OT_new", unlink="TEXT_OT_unlink")
+ layout.template_ID(context, st, "text", new="TEXT_OT_new", open="TEXT_OT_open", unlink="TEXT_OT_unlink")
if text:
row = layout.row()
@@ -213,9 +217,9 @@ class TEXT_MT_edit(bpy.types.Menu):
layout.itemS()
- layout.itemM("TEXT_MT_edit_view")
- layout.itemM("TEXT_MT_edit_select")
- layout.itemM("TEXT_MT_edit_markers")
+ layout.itemM(context, "TEXT_MT_edit_view")
+ layout.itemM(context, "TEXT_MT_edit_select")
+ layout.itemM(context, "TEXT_MT_edit_markers")
layout.itemS()
@@ -224,7 +228,7 @@ class TEXT_MT_edit(bpy.types.Menu):
layout.itemS()
- layout.itemM("TEXT_MT_edit_to3d")
+ layout.itemM(context, "TEXT_MT_edit_to3d")
bpy.types.register(TEXT_HT_header)
bpy.types.register(TEXT_PT_properties)
diff --git a/source/Makefile b/source/Makefile
index 62eb25acbc1..2df57f58c73 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -115,16 +115,25 @@ ifneq ($(NAN_NO_KETSJI),true)
COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a
COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a
+ COMLIB += $(NAN_SOLID)/lib/libsolid.a
+ COMLIB += $(NAN_SOLID)/lib/libsolid_broad.a
+ COMLIB += $(NAN_SOLID)/lib/libsolid_complex.a
+ COMLIB += $(NAN_SOLID)/lib/libsolid_convex.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
COMLIB += $(OCGDIR)/gameengine/blphys/fuzzics/$(DEBUG_DIR)libfuzzics.a
COMLIB += $(NAN_QHULL)/lib/libqhull.a
COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
+# COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
+# COMLIB += $(OCGDIR)/gameengine/blphys/blode/$(DEBUG_DIR)libblode.a
+# COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
COMLIB += $(OCGDIR)/gameengine/blphys/blbullet/$(DEBUG_DIR)libblbullet.a
COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
+# COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
COMLIB += $(OCGDIR)/gameengine/logic/$(DEBUG_DIR)liblogic.a
@@ -134,6 +143,8 @@ ifneq ($(NAN_NO_KETSJI),true)
COMLIB += $(OCGDIR)/gameengine/expression/$(DEBUG_DIR)libexpression.a
COMLIB += $(OCGDIR)/gameengine/scenegraph/$(DEBUG_DIR)libscenegraph.a
COMLIB += $(OCGDIR)/gameengine/videotex/$(DEBUG_DIR)libvideotex.a
+# COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libfuzzics.a
+# COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libsolid.a
COMLIB += $(NAN_MOTO)/lib/libmoto.a
COMLIB += $(NAN_SND_LIBS)
COMLIB += $(OCGDIR)/kernel/gen_system/$(DEBUG_DIR)libgen_system.a
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index a9e3d50211f..a53b15673e2 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -37,6 +37,7 @@ ADD_SUBDIRECTORY(imbuf/intern/cineon)
ADD_SUBDIRECTORY(gpu)
ADD_SUBDIRECTORY(makesdna)
ADD_SUBDIRECTORY(makesrna)
+ADD_SUBDIRECTORY(radiosity)
ADD_SUBDIRECTORY(readblenfile)
ADD_SUBDIRECTORY(render)
ADD_SUBDIRECTORY(blenfont)
diff --git a/source/blender/Makefile b/source/blender/Makefile
index 31636f838c3..64eb1a2614b 100644
--- a/source/blender/Makefile
+++ b/source/blender/Makefile
@@ -31,7 +31,7 @@
include nan_definitions.mk
DIRS = windowmanager editors blenloader readblenfile
-DIRS += avi imbuf render blenlib blenkernel blenpluginapi
+DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
DIRS += makesdna makesrna
DIRS += python nodes gpu
DIRS += blenfont
diff --git a/source/blender/SConscript b/source/blender/SConscript
index a064850c170..691fbf9b494 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -13,6 +13,7 @@ SConscript(['avi/SConscript',
'imbuf/intern/cineon/SConscript',
'makesdna/SConscript',
'makesrna/SConscript',
+ 'radiosity/SConscript',
'readblenfile/SConscript',
'render/SConscript',
'nodes/SConscript',
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 2ee31a17fa6..e871de490f3 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -91,21 +91,6 @@ void BLF_enable(int option);
void BLF_disable(int option);
/*
- * Shadow options, level is the blur level, can be 3, 5 or 0 and
- * the other argument are the rgba color.
- * Take care that shadow need to be enable using BLF_enable!!.
- */
-void BLF_shadow(int level, float r, float g, float b, float a);
-
-/*
- * Set the offset for shadow text, this is the current cursor
- * position plus this offset, don't need call BLF_position before
- * this function, the current position is calculate only on
- * BLF_draw, so it's safe call this whenever you like.
- */
-void BLF_shadow_offset(int x, int y);
-
-/*
* Search the path directory to the locale files, this try all
* the case for Linux, Win and Mac.
*/
@@ -134,8 +119,6 @@ void BLF_dir_free(char **dirs, int count);
#define BLF_CLIPPING (1<<1)
#define BLF_FONT_KERNING (1<<2)
#define BLF_USER_KERNING (1<<3)
-#define BLF_SHADOW (1<<4)
-#define BLF_OVERLAP_CHAR (1<<5)
/* font->mode. */
#define BLF_MODE_TEXTURE 0
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 9dad5a4bfa0..f06c7fb0d28 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -500,28 +500,3 @@ void BLF_kerning(float space)
if (font)
font->kerning= space;
}
-
-void BLF_shadow(int level, float r, float g, float b, float a)
-{
- FontBLF *font;
-
- font= global_font[global_font_cur];
- if (font) {
- font->shadow= level;
- font->shadow_col[0]= r;
- font->shadow_col[1]= g;
- font->shadow_col[2]= b;
- font->shadow_col[3]= a;
- }
-}
-
-void BLF_shadow_offset(int x, int y)
-{
- FontBLF *font;
-
- font= global_font[global_font_cur];
- if (font) {
- font->shadow_x= x;
- font->shadow_y= y;
- }
-}
diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c
index 92dfe8457b0..88b0105a292 100644
--- a/source/blender/blenfont/intern/blf_dir.c
+++ b/source/blender/blenfont/intern/blf_dir.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: blf_dir.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index a3c5232cc76..ee4ba0ee71a 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -146,22 +146,20 @@ void blf_font_draw(FontBLF *font, char *str)
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
pen_x += delta.x >> 6;
-
- if (font->flags & BLF_OVERLAP_CHAR) {
- if (pen_x < old_pen_x)
- pen_x= old_pen_x;
- }
+/*
+ if (pen_x < old_pen_x)
+ pen_x= old_pen_x;
+*/
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
-
- if (font->flags & BLF_OVERLAP_CHAR) {
- if (pen_x < old_pen_x)
- pen_x= old_pen_x;
- }
+/*
+ if (pen_x < old_pen_x)
+ pen_x= old_pen_x;
+*/
}
/* do not return this loop if clipped, we want every character tested */
@@ -230,22 +228,20 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
pen_x += delta.x >> 6;
-
- if (font->flags & BLF_OVERLAP_CHAR) {
- if (pen_x < old_pen_x)
- pen_x= old_pen_x;
- }
+/*
+ if (pen_x < old_pen_x)
+ old_pen_x= pen_x;
+*/
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
-
- if (font->flags & BLF_OVERLAP_CHAR) {
- if (pen_x < old_pen_x)
- pen_x= old_pen_x;
- }
+/*
+ if (pen_x < old_pen_x)
+ old_pen_x= pen_x;
+*/
}
gbox.xmin= g->box.xmin + pen_x;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index a637774d7bf..33a435cc5be 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -496,20 +496,8 @@ int blf_glyph_texture_render(FontBLF *font, GlyphBLF *g, float x, float y)
GLint cur_tex;
float dx, dx1;
float y1, y2;
- float xo, yo;
- float color[4];
gt= g->tex_data;
- xo= 0.0f;
- yo= 0.0f;
-
- if (font->flags & BLF_SHADOW) {
- xo= x;
- yo= y;
- x += font->shadow_x;
- y += font->shadow_y;
- }
-
dx= floor(x + gt->pos_x);
dx1= dx + gt->width;
y1= y + gt->pos_y;
@@ -530,27 +518,6 @@ int blf_glyph_texture_render(FontBLF *font, GlyphBLF *g, float x, float y)
if (cur_tex != gt->tex)
glBindTexture(GL_TEXTURE_2D, gt->tex);
- if (font->flags & BLF_SHADOW) {
- glGetFloatv(GL_CURRENT_COLOR, color);
- glColor4fv(font->shadow_col);
-
- if (font->shadow == 3)
- blf_texture3_draw(gt->uv, dx, y1, dx1, y2);
- else if (font->shadow == 5)
- blf_texture5_draw(gt->uv, dx, y1, dx1, y2);
- else
- blf_texture_draw(gt->uv, dx, y1, dx1, y2);
-
- glColor4fv(color);
- x= xo;
- y= yo;
-
- dx= floor(x + gt->pos_x);
- dx1= dx + gt->width;
- y1= y + gt->pos_y;
- y2= y + gt->pos_y - gt->height;
- }
-
if (font->blur==3)
blf_texture3_draw(gt->uv, dx, y1, dx1, y2);
else if (font->blur==5)
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index c9bdc428ebb..af237690b58 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: blf_internal.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 5382ac19aae..ba988c522f0 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: blf_internal_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -154,16 +154,6 @@ typedef struct FontBLF {
/* blur: 3 or 5 large kernel */
int blur;
-
- /* shadow level. */
- int shadow;
-
- /* and shadow offset. */
- int shadow_x;
- int shadow_y;
-
- /* shadow color. */
- float shadow_col[4];
/* this is the matrix that we load before rotate/scale/translate. */
float mat[4][4];
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 024172d6db4..757a18f0165 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: blf_lang.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 4270c677338..e09be838f06 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -46,7 +46,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "BKE_collision.h"
@@ -246,8 +245,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
// needed for editmesh.c
-void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr );
-int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr );
+void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
+int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr );
// needed for button_object.c
void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr );
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index f536e117b7b..1845665a96d 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BKE_context.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -131,7 +131,6 @@ void CTX_wm_menu_set(bContext *C, struct ARegion *menu);
- the dir listbase consits of LinkData items */
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
-PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type);
ListBase CTX_data_collection_get(const bContext *C, const char *member);
ListBase CTX_data_dir_get(const bContext *C);
void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h
index 5c47eeabfe8..11dc1f41109 100644
--- a/source/blender/blenkernel/BKE_exotic.h
+++ b/source/blender/blenkernel/BKE_exotic.h
@@ -47,6 +47,7 @@ int BKE_read_exotic(struct Scene *scene, char *name);
void write_dxf(struct Scene *scene, char *str);
void write_vrml(struct Scene *scene, char *str);
+void write_videoscape(struct Scene *scene, char *str);
void write_stl(struct Scene *scene, char *str);
#endif
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 1892c8e71a4..581285be21c 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BDR_gpencil.h 19541 2009-04-05 06:54:47Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 382754ee2b2..38a1d9b13b7 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -39,8 +39,6 @@ struct Material;
struct ID;
struct Object;
-/* materials */
-
void init_def_material(void);
void free_material(struct Material *sc);
void test_object_materials(struct ID *id);
@@ -49,22 +47,15 @@ struct Material *add_material(char *name);
struct Material *copy_material(struct Material *ma);
void make_local_material(struct Material *ma);
-void automatname(struct Material *);
-
-/* material slots */
-
struct Material ***give_matarar(struct Object *ob);
short *give_totcolp(struct Object *ob);
struct Material *give_current_material(struct Object *ob, int act);
struct ID *material_from(struct Object *ob, int act);
void assign_material(struct Object *ob, struct Material *ma, int act);
+void new_material_to_objectdata(struct Object *ob);
int find_material_index(struct Object *ob, struct Material *ma);
-void object_add_material_slot(struct Object *ob);
-void object_remove_material_slot(struct Object *ob);
-
-/* rendering */
void init_render_material(struct Material *, int, float *);
void init_render_materials(int, float *);
@@ -73,8 +64,12 @@ void end_render_materials(void);
int material_in_material(struct Material *parmat, struct Material *mat);
+void automatname(struct Material *);
+void delete_material_index(struct Object *ob);
+
void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 4d9916b9557..4efd9a7f8ba 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -217,8 +217,6 @@ char *psys_menu_string(struct Object *ob, int for_sb);
struct ParticleSystem *psys_get_current(struct Object *ob);
short psys_get_current_num(struct Object *ob);
-void psys_set_current_num(Object *ob, int index);
-struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
//struct ParticleSystem *psys_get(struct Object *ob, int index);
struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index);
struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index);
@@ -251,8 +249,6 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim
void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor);
struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
-void object_add_particle_system_slot(struct Scene *scene, struct Object *ob);
-void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob);
struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
@@ -294,13 +290,10 @@ void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, str
void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys);
void psys_end_effectors(struct ParticleSystem *psys);
-void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra);
-
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* ----------- functions needed only inside particlesystem ------------ */
/* particle.c */
-void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity);
void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]);
//void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
//void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 3f1c45d28ec..8ef3ff4d4b7 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -31,8 +31,6 @@
#include "DNA_ID.h"
-#include "MEM_guardedalloc.h"
-
/* Point cache clearing option, for BKE_ptcache_id_clear, before
* and after are non inclusive (they wont remove the cfra) */
#define PTCACHE_CLEAR_ALL 0
@@ -44,7 +42,6 @@
#define PTCACHE_RESET_DEPSGRAPH 0
#define PTCACHE_RESET_BAKED 1
#define PTCACHE_RESET_OUTDATED 2
-#define PTCACHE_RESET_FREE 3
/* Add the blendfile name after blendcache_ */
#define PTCACHE_EXT ".bphys"
@@ -59,11 +56,6 @@
#define PTCACHE_TYPE_PARTICLES 1
#define PTCACHE_TYPE_CLOTH 2
-/* PTCache read return code */
-#define PTCACHE_READ_EXACT 1
-#define PTCACHE_READ_INTERPOLATED 2
-#define PTCACHE_READ_OLD 3
-
/* Structs */
struct Object;
struct Scene;
@@ -88,40 +80,6 @@ typedef struct PTCacheID {
struct PointCache *cache;
} PTCacheID;
-typedef struct PTCacheWriter {
- struct PTCacheID *pid;
- int cfra;
- int totelem;
-
- void (*set_elem)(int index, void *calldata, float *data);
- void *calldata;
-} PTCacheWriter;
-
-typedef struct PTCacheReader {
- struct Scene *scene;
- struct PTCacheID *pid;
- float cfra;
- int totelem;
-
- void (*set_elem)(int elem_index, void *calldata, float *data);
- void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2);
- void *calldata;
-
- int *old_frame;
-} PTCacheReader;
-
-typedef struct PTCacheBaker {
- struct Scene *scene;
- int bake;
- int render;
- int quick_step;
- struct PTCacheID *pid;
- int (*break_test)(void *data);
- void *break_data;
- void (*progressbar)(void *data, int num);
- void *progresscontext;
-} PTCacheBaker;
-
/* Creating ID's */
void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
@@ -135,9 +93,9 @@ void BKE_ptcache_remove(void);
/* ID specific functions */
void BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra);
int BKE_ptcache_id_exist(PTCacheID *id, int cfra);
-int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode);
+int BKE_ptcache_id_reset(PTCacheID *id, int mode);
void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale);
-int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode);
+int BKE_ptcache_object_reset(struct Object *ob, int mode);
/* File reading/writing */
PTCacheFile *BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra);
@@ -145,12 +103,6 @@ void BKE_ptcache_file_close(PTCacheFile *pf);
int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot);
int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot);
-void BKE_ptcache_update_info(PTCacheID *pid);
-
-/* General cache reading/writing */
-int BKE_ptcache_read_cache(PTCacheReader *reader);
-int BKE_ptcache_write_cache(PTCacheWriter *writer);
-
/* Continue physics */
void BKE_ptcache_set_continue_physics(struct Scene *scene, int enable);
int BKE_ptcache_get_continue_physics(void);
@@ -160,9 +112,4 @@ struct PointCache *BKE_ptcache_add(void);
void BKE_ptcache_free(struct PointCache *cache);
struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
-/* Baking */
-void BKE_ptcache_quick_cache_all(struct Scene *scene);
-void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
-void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
-
#endif
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index 21221026b8b..60e48004fb1 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BKE_report.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h
index 65a3b0216fe..93f68f00d2f 100644
--- a/source/blender/blenkernel/BKE_sequence.h
+++ b/source/blender/blenkernel/BKE_sequence.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BKE_sequence.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index 419f0f5beeb..6584af085cd 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -130,7 +130,7 @@
#define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0))
/* this weirdo pops up in two places ... */
-#if !defined(WIN32)
+#if !defined(WIN32) && !defined(__BeOS)
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -148,6 +148,12 @@
#define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid
#define FORM MAKE_ID('F','O','R','M')
+#define DDG1 MAKE_ID('3','D','G','1')
+#define DDG2 MAKE_ID('3','D','G','2')
+#define DDG3 MAKE_ID('3','D','G','3')
+#define DDG4 MAKE_ID('3','D','G','4')
+
+#define GOUR MAKE_ID('G','O','U','R')
#define BLEN MAKE_ID('B','L','E','N')
#define DER_ MAKE_ID('D','E','R','_')
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 441e17f3318..30dcb383ef6 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -43,7 +43,6 @@ static short id_has_animdata (ID *id)
case ID_OB:
case ID_CU:
case ID_KE:
- case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
case ID_SCE:
@@ -884,9 +883,6 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
/* meshes */
// TODO...
- /* particles */
- EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM);
-
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index d3d21018c1c..5fc7d18689d 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -221,6 +221,7 @@ static void clear_global(void)
{
// extern short winqueue_break; /* screen.c */
+// XXX freeAllRad();
fastshade_free_render(); /* lamps hang otherwise */
free_main(G.main); /* free all lib data */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 08caea565aa..e98d7bb01a4 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -33,7 +33,6 @@
#include "DNA_mesh_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
@@ -43,7 +42,6 @@
#include "BKE_object.h"
#include "BKE_modifier.h"
#include "BKE_utildefines.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -341,99 +339,78 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
-static void cloth_write_state(int index, Cloth *cloth, float *data)
-{
- ClothVertex *vert = cloth->verts + index;
-
- memcpy(data, vert->x, 3 * sizeof(float));
- memcpy(data + 3, vert->xconst, 3 * sizeof(float));
- memcpy(data + 6, vert->v, 3 * sizeof(float));
-}
-static void cloth_read_state(int index, Cloth *cloth, float *data)
-{
- ClothVertex *vert = cloth->verts + index;
-
- memcpy(vert->x, data, 3 * sizeof(float));
- memcpy(vert->xconst, data + 3, 3 * sizeof(float));
- memcpy(vert->v, data + 6, 3 * sizeof(float));
-}
-static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
-{
- ClothVertex *vert = cloth->verts + index;
- ParticleKey keys[4];
- float dfra;
-
- if(cfra1 == cfra2) {
- cloth_read_state(index, cloth, data1);
- return;
- }
-
- memcpy(keys[1].co, data1, 3 * sizeof(float));
- memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float));
-
- memcpy(keys[2].co, data2, 3 * sizeof(float));
- memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float));
-
- dfra = cfra2 - cfra1;
-
- VecMulf(keys[1].vel, dfra);
- VecMulf(keys[2].vel, dfra);
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
-
- VecMulf(keys->vel, 1.0f / dfra);
-
- memcpy(vert->x, keys->co, 3 * sizeof(float));
- memcpy(vert->v, keys->vel, 3 * sizeof(float));
-
- /* not sure what to do with this - jahka */
- memcpy(vert->xconst, data1 + 3, 3 * sizeof(float));
-}
-void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra)
+int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
{
- PTCacheWriter writer;
PTCacheID pid;
-
+ PTCacheFile *pf;
+ Cloth *cloth = clmd->clothObject;
+ unsigned int a, ret = 1;
+
+ if(!cloth)
+ return 0;
+
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-
- writer.calldata = clmd->clothObject;
- writer.cfra = cfra;
- writer.set_elem = cloth_write_state;
- writer.pid = &pid;
- writer.totelem = clmd->clothObject->numverts;
-
- BKE_ptcache_write_cache(&writer);
+ pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr);
+ if(pf) {
+ for(a = 0; a < cloth->numverts; a++) {
+ if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) {
+ ret = 0;
+ break;
+ }
+ if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
+ ret = 0;
+ break;
+ }
+ if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
+ ret = 0;
+ break;
+ }
+ }
+
+ BKE_ptcache_file_close(pf);
+ }
+ else
+ ret = 0;
+
+ return ret;
}
-int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
+void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
{
- PTCacheReader reader;
PTCacheID pid;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
- reader.calldata = clmd->clothObject;
- reader.cfra = cfra;
- reader.interpolate_elem = cloth_cache_interpolate;
- reader.old_frame = old_framenr;
- reader.pid = &pid;
- reader.scene = scene;
- reader.set_elem = cloth_read_state;
- reader.totelem = clmd->clothObject->numverts;
-
- return BKE_ptcache_read_cache(&reader);
+ // don't do anything as long as we're in editmode!
+ if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
+ return;
+
+ BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
}
-void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+
+void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
{
+ Cloth *cloth = clmd->clothObject;
PTCacheID pid;
+ PTCacheFile *pf;
+ unsigned int a;
+
+ if(!cloth)
+ return;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-
- // don't do anything as long as we're in editmode!
- if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
+ pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
+ if(!pf)
return;
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
+ for(a = 0; a < cloth->numverts; a++) {
+ BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3);
+ BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3);
+ BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3);
+ }
+
+ BKE_ptcache_file_close(pf);
}
static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
@@ -509,7 +486,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
PTCacheID pid;
float timescale;
int framedelta, framenr, startframe, endframe;
- int cache_result, old_framenr;
clmd->scene= scene; /* nice to pass on later :) */
framenr= (int)scene->r.cfra;
@@ -523,7 +499,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(!result) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
return dm;
}
@@ -535,7 +510,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(result->getNumVerts(result) != clmd->clothObject->numverts) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
return result;
}
}
@@ -547,7 +521,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(BKE_ptcache_get_continue_physics()) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
/* do simulation */
if(!do_init_cloth(ob, clmd, result, framenr))
@@ -563,7 +536,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(framenr < startframe) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
return result;
}
else if(framenr > endframe) {
@@ -580,9 +552,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return result;
/* try to read from cache */
- cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
-
- if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
+ if(cloth_read_cache(ob, clmd, framenr)) {
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
@@ -591,40 +561,25 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return result;
}
- else if(cache_result==PTCACHE_READ_OLD) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
-
- implicit_set_positions(clmd);
-
- cache->flag |= PTCACHE_SIMULATION_VALID;
- cache->simframe= old_framenr;
- }
else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
/* if baked and nothing in cache, do nothing */
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
return result;
}
if(framenr == startframe) {
- if(cache->flag & PTCACHE_REDO_NEEDED) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- do_init_cloth(ob, clmd, result, framenr);
- }
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
/* don't write cache on first frame, but on second frame write
* cache for frame 1 and 2 */
}
- else {
+ else if(framedelta == 1) {
/* if on second frame, write cache for first frame */
- if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
+ if(framenr == startframe+1)
cloth_write_cache(ob, clmd, startframe);
- clmd->sim_parms->timescale *= framenr - cache->simframe;
-
/* do simulation */
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
@@ -632,13 +587,16 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(!do_step_cloth(ob, clmd, result, framenr)) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
}
else
cloth_write_cache(ob, clmd, framenr);
cloth_to_object (ob, clmd, result);
}
+ else {
+ cache->flag &= ~PTCACHE_SIMULATION_VALID;
+ cache->simframe= 0;
+ }
return result;
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 88e73a00ba7..a43389a2ef6 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3028,7 +3028,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
if (VALID_CONS_TARGET(ct)) {
float loc[3], eul[3], size[3];
float dvec[3], sval[3];
- int i;
+ short i;
/* obtain target effect */
switch (data->from) {
@@ -3075,7 +3075,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
switch (data->to) {
case 2: /* scaling */
for (i=0; i<3; i++)
- size[i]= data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i]));
+ size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i]));
break;
case 1: /* rotation */
for (i=0; i<3; i++) {
@@ -3085,7 +3085,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
tmax= data->to_max[i];
/* all values here should be in degrees */
- eul[i]= tmin + (sval[(int)data->map[i]] * (tmax - tmin));
+ eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin));
/* now convert final value back to radians */
eul[i] = (float)(eul[i] / 180 * M_PI);
@@ -3094,7 +3094,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
default: /* location */
/* get new location */
for (i=0; i<3; i++)
- loc[i]= (data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])));
+ loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])));
/* add original location back on (so that it can still be moved) */
VecAddf(loc, cob->matrix[3], loc);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index fbad585d9b7..6afbcf4950c 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: context.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -358,9 +358,6 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
return 1;
}
- list->first= NULL;
- list->last= NULL;
-
return 0;
}
@@ -368,20 +365,15 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
{
bContextDataResult result;
- if(ctx_data_get((bContext*)C, member, &result))
+ if(ctx_data_get((bContext*)C, member, &result)) {
return result.ptr;
- else
- return PointerRNA_NULL;
-}
-
-PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
-{
- PointerRNA ptr = CTX_data_pointer_get(C, member);
-
- if(ptr.data && ptr.type == type)
+ }
+ else {
+ PointerRNA ptr;
+ memset(&ptr, 0, sizeof(ptr));
return ptr;
-
- return PointerRNA_NULL;
+ }
+
}
ListBase CTX_data_collection_get(const bContext *C, const char *member)
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index a36b825293e..8bb34bde122 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -559,7 +559,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
- if(!psys_check_enabled(ob, psys))
+ if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE)
continue;
if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob &&
@@ -1831,7 +1831,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
}
/* node was checked to have lasttime != curtime , and is of type ID_OB */
-static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset)
+static void flush_pointcache_reset(DagNode *node, int curtime, int reset)
{
DagAdjList *itA;
Object *ob;
@@ -1844,13 +1844,13 @@ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int
ob= (Object*)(node->ob);
if(reset || (ob->recalc & OB_RECALC)) {
- if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
+ if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
ob->recalc |= OB_RECALC_DATA;
- flush_pointcache_reset(scene, itA->node, curtime, 1);
+ flush_pointcache_reset(itA->node, curtime, 1);
}
else
- flush_pointcache_reset(scene, itA->node, curtime, 0);
+ flush_pointcache_reset(itA->node, curtime, 0);
}
}
}
@@ -1908,13 +1908,13 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time)
ob= (Object*)(itA->node->ob);
if(ob->recalc & OB_RECALC) {
- if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH))
+ if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
ob->recalc |= OB_RECALC_DATA;
- flush_pointcache_reset(sce, itA->node, lasttime, 1);
+ flush_pointcache_reset(itA->node, lasttime, 1);
}
else
- flush_pointcache_reset(sce, itA->node, lasttime, 0);
+ flush_pointcache_reset(itA->node, lasttime, 0);
}
}
}
@@ -2132,7 +2132,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag)
if(ob==NULL || sce->theDag==NULL) return;
ob->recalc |= flag;
- BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
+ BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH);
/* all users of this ob->data should be checked */
/* BUT! displists for curves are still only on cu */
@@ -2147,7 +2147,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag)
for (obt=G.main->object.first; obt; obt= obt->id.next) {
if (obt != ob && obt->data==ob->data) {
obt->recalc |= OB_RECALC_DATA;
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
+ BKE_ptcache_object_reset(obt, PTCACHE_RESET_DEPSGRAPH);
}
}
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cdf4b90cee1..736165a8a98 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -315,19 +315,13 @@ static void init_fastshade_shadeinput(Render *re)
static Render *fastshade_get_render(Scene *scene)
{
- /* XXX ugly global still, but we can't do preview while rendering */
- if(G.rendering==0) {
-
- Render *re= RE_GetRender("_Shade View_");
- if(re==NULL) {
- re= RE_NewRender("_Shade View_");
-
- RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */
- }
- return re;
- }
+ Render *re= RE_GetRender("_Shade View_");
+ if(re==NULL) {
+ re= RE_NewRender("_Shade View_");
- return NULL;
+ RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */
+ }
+ return re;
}
/* called on file reading */
@@ -617,20 +611,18 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me)
{
- Render *re= fastshade_get_render(scene);
int a;
char *cp;
unsigned int *mcol= (unsigned int*)me->mcol;
- if(re) {
- mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
- me->mcol= (MCol*)mcol;
+ Render *re= fastshade_get_render(scene);
+ mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
+ me->mcol= (MCol*)mcol;
- /* swap bytes */
- for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
- SWAP(char, cp[0], cp[3]);
- SWAP(char, cp[1], cp[2]);
- }
+ /* swap bytes */
+ for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
+ SWAP(char, cp[0], cp[3]);
+ SWAP(char, cp[1], cp[2]);
}
}
@@ -649,8 +641,6 @@ void shadeDispList(Scene *scene, Base *base)
int a, need_orco;
re= fastshade_get_render(scene);
- if(re==NULL)
- return;
dl = find_displist(&ob->disp, DL_VERTCOL);
if (dl) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index eaa2d541638..9858025af5a 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -29,8 +29,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
-
#include <math.h>
#include <stdlib.h>
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index 4e7e76dfae3..929d3f942dc 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -27,9 +27,48 @@
*
* - Blender Foundation
*
- * ***** END GPL LICENSE BLOCK *****/
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * eigen videoscape formaat:
+ *
+ *
+ * lamp:
+ * 3DG2
+ aantal_lampen
+
+ type
+ spsi spbl
+ r, g, b, energy
+ locx, locy, locz
+ vecx, vecy, vecz
+
+
+ curve / nurbs:
+ 3DG3
+ 5 of 11 (curve of surf)
+ aantal_nurbs
+ extr1 extr2
+
+ mat[0][0] mat[0][1] mat[0][2] mat[0][3]
+ mat[1][0] mat[1][1] mat[1][2] mat[1][3]
+ ...
+
+ type
+ pntsu, pntsv
+ resolu, resolv
+ orderu, orderv
+ flagu, flagv
+
+ (als type==nurb) x y z w
+ x y z w
+ ...
+ (als type==bez) xyz xyz xyz h1 h2 h3
+ xyz xyz xyz h1 h2 h3
+ ...
+ *
+ *
+ */
-#include "BLI_storage.h"
#include <ctype.h> /* isdigit, isspace */
#include <math.h>
@@ -443,6 +482,385 @@ static void read_stl_mesh_ascii(Scene *scene, char *str)
#undef STLREADLINE
#undef STLREADVERT
+static void read_videoscape_mesh(Scene *scene, char *str)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma;
+ FILE *fp;
+ float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
+ unsigned int color[32], col;
+ int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
+ int end;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ //XXX error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+
+ fscanf(fp, "%d\n", &verts);
+ if(verts<=0) {
+ fclose(fp);
+ //XXX error("Read error");
+ return;
+ }
+
+ if(verts>MESH_MAX_VERTS) {
+ //XXX error("too many vertices");
+ fclose(fp);
+ return;
+ }
+
+ INIT_MINMAX(min, max);
+ vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
+
+ for(a=0; a<verts; a++) {
+ fscanf(fp, "%f %f %f", vd, vd+1, vd+2);
+ DO_MINMAX(vd, min, max);
+ vd+=3;
+ }
+
+ /* count faces and colors */
+ for(a=0; a<32; a++) color[a]= 0;
+ totcol= 0;
+ end= 1;
+ while(end>0) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3) tottria++;
+ else if(poly==4) totquad++;
+ else totedge+= poly;
+
+ for(a=0;a<poly;a++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ }
+ if(end<=0) break;
+
+ end= fscanf(fp,"%i\n", &col);
+ col &= 0xF0F0F0;
+ for(a=0; a<totcol; a++) {
+ if(color[a]==col) break;
+ }
+ if(a>=totcol && totcol<32) {
+ color[totcol]= col;
+ totcol++;
+ }
+ }
+
+ /* new object */
+ ob= add_object(scene, OB_MESH);
+ me= ob->data;
+ me->totvert= verts;
+ me->totface= totedge+tottria+totquad;
+
+ me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC,
+ NULL, me->totvert);
+ me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC,
+ NULL, me->totface);
+
+ /* colors */
+ if(totcol) {
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
+ me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
+ me->totcol= totcol;
+ ob->totcol= (unsigned char) me->totcol;
+ ob->actcol= 1;
+ }
+
+ /* materials */
+ for(a=0; a<totcol; a++) {
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ col= rgb_to_cpack(ma->r, ma->g, ma->b);
+ if(color[a]==col) {
+ me->mat[a]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[a]= ma;
+ cpack_to_rgb(color[a], cent, cent+1, cent+2);
+ ma->r= cent[0];
+ ma->g= cent[1];
+ ma->b= cent[2];
+ automatname(ma);
+ }
+ }
+
+ /* verts */
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ VECCOPY(ob->loc, cent);
+
+ a= me->totvert;
+ vd= vertdata;
+ mvert= me->mvert;
+ while(a--) {
+ VecSubf(mvert->co, vd, cent);
+ mvert++;
+ vd+= 3;
+ }
+
+ /* faces */
+ if(me->totface) {
+ rewind(fp);
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &verts);
+ /* fake read */
+ for(a=0;a<verts;a++) {
+ fscanf(fp, "%f %f %f", &ftemp, &ftemp, &ftemp);
+ }
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3 || poly==4) {
+ fscanf(fp,"%d", &nr);
+ mface->v1= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v2= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v3= MIN2(nr, me->totvert-1);
+ if(poly==4) {
+ if( fscanf(fp,"%d", &nr) <=0 ) break;
+ mface->v4= MIN2(nr, me->totvert-1);
+ }
+
+ test_index_face(mface, NULL, 0, poly);
+
+ mface++;
+ }
+ else {
+ if( fscanf(fp,"%d", &nr0) <=0) break;
+ first= nr0;
+ for(b=1; b<poly; b++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ nr= MIN2(nr, me->totvert-1);
+ mface->v1= nr;
+ mface->v2= nr0;
+ nr0= nr;
+ mface++;
+ a--;
+ }
+ mface->v1= first;
+ mface->v2= nr;
+ mface++;
+ if(end<=0) break;
+ }
+ end= fscanf(fp,"%i", &col);
+ col &= 0xF0F0F0;
+ if(end<=0) break;
+
+ for(b=0; b<totcol; b++) {
+ if(color[b]==col) {
+ (mface-1)->mat_nr= b;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(fp);
+ MEM_freeN(vertdata);
+
+ mesh_add_normals_flags(me);
+ make_edges(me, 0);
+
+ //XXX waitcursor(1);
+}
+
+static void read_videoscape_lamp(Scene *scene, char *str)
+{
+ Object *ob;
+ Lamp *la;
+ FILE *fp;
+ float vec[3], q1[4];
+ int tot, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ //XXX error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &tot);
+
+ while(tot--) {
+ ob= add_object(scene, OB_LAMP);
+ la= ob->data;
+
+ fscanf(fp, "%d\n", &val);
+ la->type= val;
+ if(la->type==1) la->type= LA_SPOT;
+ else if(la->type==2) la->type= LA_SUN;
+
+ fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
+
+ fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);
+
+ fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
+ val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
+ vectoquat(vec, 5, 2, q1);
+ QuatToEul(q1, ob->rot);
+
+ if(val<=0) break;
+
+ }
+ fclose(fp);
+}
+
+static void read_videoscape_nurbs(Scene *scene, char *str)
+{
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ FILE *fp;
+ float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
+ int a, tot, type, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ //XXX error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &type);
+
+ if(type==5) ob= add_object(scene, OB_SURF);
+ else ob= add_object(scene, OB_CURVE);
+ cu= ob->data;
+
+ fscanf(fp, "%d\n", &tot);
+ fscanf(fp, "%d %d\n", &type, &val);
+
+ cu->ext1= 0.002f*type;
+ cu->ext2= 0.002f*val;
+
+ for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
+
+ VECCOPY(ob->loc, tmat[3]);
+
+ Mat3CpyMat4(omat, tmat);
+ Mat3ToEul(omat, ob->rot);
+ EulToMat3(ob->rot, mat);
+ Mat3Inv(imat, mat);
+ Mat3MulMat3((float ( * )[3])tmat, imat, omat);
+
+ while(tot--) {
+ nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
+ BLI_addtail(&cu->nurb, nu);
+
+ fscanf(fp, "%d\n", &type);
+ nu->type= type;
+
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->pntsu= type; nu->pntsv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->resolu= type; nu->resolv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->orderu= type; nu->orderv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->flagu= type; nu->flagv= val;
+
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
+ Mat4MulVecfl(tmat, bezt->vec[0]);
+ fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
+ Mat4MulVecfl(tmat, bezt->vec[1]);
+ fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
+ Mat4MulVecfl(tmat, bezt->vec[2]);
+ fscanf(fp, "%d %d\n", &type, &val);
+ bezt->h1= type;
+ bezt->h2= val;
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ if(a) {
+ nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
+ Mat4MulVecfl(tmat, bp->vec);
+ bp++;
+ }
+
+ val= KNOTSU(nu);
+ nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsu+a);
+
+ if(nu->pntsv>1) {
+ val= KNOTSV(nu);
+ nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsv+a);
+ }
+ }
+ else {
+ BLI_remlink(&cu->nurb, nu);
+ MEM_freeN(nu);
+ }
+ }
+ }
+ fclose(fp);
+}
+
+static void read_videoscape(Scene *scene, char *str)
+{
+ int file, type;
+ unsigned int val;
+ unsigned short numlen;
+ char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ strcpy(name, str);
+
+ while( TRUE ) {
+ file= open(name, O_BINARY|O_RDONLY);
+ if(file<=0) break;
+ else {
+ read(file, &type, 4);
+ close(file);
+
+ if(type==DDG1) read_videoscape_mesh(scene, name);
+ else if(type==DDG2) read_videoscape_lamp(scene, name);
+ else if(type==DDG3) read_videoscape_nurbs(scene, name);
+ }
+
+ val = BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, val + 1);
+
+ }
+}
+
+
/* ***************** INVENTOR ******************* */
@@ -1786,7 +2204,16 @@ int BKE_read_exotic(Scene *scene, char *name)
if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) {
//XXX waitcursor(1);
- if(strncmp(str, "#Inventor V1.0", 14)==0) {
+
+ if(ELEM4(*s0, DDG1, DDG2, DDG3, DDG4)) {
+ if(0) { // XXX obedit) {
+ //XXX error("Unable to perform function in EditMode");
+ } else {
+ read_videoscape(scene, name);
+ retval = 1;
+ }
+ }
+ else if(strncmp(str, "#Inventor V1.0", 14)==0) {
if( strncmp(str+15, "ascii", 5)==0) {
read_inventor(scene, name, &lbase);
displist_to_objects(scene, &lbase);
@@ -1958,6 +2385,167 @@ void write_stl(Scene *scene, char *str)
//XXX waitcursor(0);
}
+static void write_videoscape_mesh(Scene *scene, Object *ob, char *str)
+{
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+ Material *ma;
+ MFace *mface;
+ FILE *fp;
+ EditVert *eve;
+ EditFace *evl;
+ unsigned int kleur[32];
+ float co[3];
+ int a;
+ intptr_t tot;
+ char *cp;
+
+ if(ob && ob->type==OB_MESH);
+ else {
+ return;
+ }
+
+ kleur[0]= 0x00C0C0C0;
+
+ cp= (char *)kleur;
+ for(a=0; a<ob->totcol; a++, cp+=4) {
+
+ ma= give_current_material(ob, a+1);
+ if(ma) {
+ cp[0]= (unsigned char) (255.0*ma->emit);
+ cp[1]= (unsigned char) (255.0*ma->b);
+ cp[2]= (unsigned char) (255.0*ma->g);
+ cp[3]= (unsigned char) (255.0*ma->r);
+ if(ENDIAN_ORDER==L_ENDIAN) SWITCH_INT(kleur[a]);
+ }
+ else kleur[a]= 0x00C0C0C0;
+
+ if(a>30) break;
+ }
+
+ fp= fopen(str, "wb");
+ if(fp==NULL) return;
+
+ fprintf(fp,"3DG1\n");
+
+ if(em) {
+
+ fprintf(fp, "%d\n", em->totvert);
+
+ tot= 0;
+ eve= em->verts.first;
+ while(eve) {
+ VECCOPY(co, eve->co);
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ eve->tmp.l = tot;
+ tot++;
+ eve= eve->next;
+ }
+ evl= em->faces.first;
+ while(evl) {
+
+ if(evl->v4==0) {
+ fprintf(fp, "3 %ld %ld %ld 0x%x\n",
+ (intptr_t) evl->v1->tmp.l,
+ (intptr_t) evl->v2->tmp.l,
+ (intptr_t) evl->v3->tmp.l,
+ kleur[evl->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n",
+ (intptr_t) evl->v1->tmp.l,
+ (intptr_t) evl->v2->tmp.l,
+ (intptr_t) evl->v3->tmp.l,
+ (intptr_t) evl->v4->tmp.l,
+ kleur[evl->mat_nr]);
+ }
+ evl= evl->next;
+ }
+ }
+ else {
+ DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+
+ me= ob->data;
+
+ fprintf(fp, "%d\n", me->totvert);
+
+ mface= me->mface;
+ for(a=0; a<me->totvert; a++) {
+ dm->getVertCo(dm, a, co);
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ }
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v4==0) {
+ fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[(int)mface->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[(int)mface->mat_nr]);
+ }
+ }
+
+ dm->release(dm);
+ }
+
+ fclose(fp);
+
+ if (em) BKE_mesh_end_editmesh(me, em);
+
+}
+
+
+void write_videoscape(Scene *scene, char *str)
+{
+ Base *base;
+ int file, val, lampdone=0;
+ unsigned short numlen;
+ char head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
+
+ file= open(str,O_BINARY|O_RDONLY);
+ close(file);
+ //XXX saveover()
+ // if(file>-1) if(!during_script() && saveover(str)==0) return;
+
+ strcpy(temp_dir, str);
+
+ base= scene->base.first;
+ while(base) {
+ if((base->flag & SELECT) && (base->lay & scene->lay)) {
+ if(base->object->type==OB_MESH) {
+ write_videoscape_mesh(scene, base->object, str);
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+ else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
+ /* write_videoscape_nurbs(base->object, str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ else if(lampdone==0 && base->object->type==OB_LAMP) {
+ /* lampdone= 1; */
+ /* write_videoscape_lamps(str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ }
+ base= base->next;
+ }
+
+
+ /* remove when higher numbers exist */
+ while(remove(str)==0) {
+
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+}
+
/* ******************************* WRITE VRML ***************************** */
static void replace_chars(char *str1, char *str2)
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 54008185f72..9eefd48cae4 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -28,8 +28,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
-
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index dd8f44c71d5..6086aa58d40 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 54366aadd92..3be47778674 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -230,16 +230,16 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
*/
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
- newarr = MEM_callocN(idp_size_table[(int)prop->subtype]*newsize, "idproperty array resized");
+ newarr = MEM_callocN(idp_size_table[prop->subtype]*newsize, "idproperty array resized");
if (newlen >= prop->len) {
/* newlen is bigger*/
- memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[(int)prop->subtype]);
+ memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[prop->subtype]);
idp_resize_group_array(prop, newlen, newarr);
}
else {
/* newlen is smaller*/
idp_resize_group_array(prop, newlen, newarr);
- memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[(int)prop->subtype]);
+ memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[prop->subtype]);
}
MEM_freeN(prop->data.pointer);
@@ -546,7 +546,7 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
return BSTR_EQ(IDP_String(prop1), IDP_String(prop2));
else if(prop1->type == IDP_ARRAY) {
if(prop1->len == prop2->len && prop1->subtype == prop2->subtype)
- return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype]*prop1->len);
+ return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[prop1->subtype]*prop1->len);
else
return 0;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 6b231cfc702..8eef9984c92 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1812,7 +1812,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser)
Render *re= NULL;
RenderResult *rr= NULL;
- if(iuser && iuser->scene) {
+ if(iuser->scene) {
re= RE_GetRender(iuser->scene->id.name);
rr= RE_GetResult(re);
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index fc5213d5532..40c98c1d9cc 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1600,10 +1600,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
{
- float temp = clmd->sim_parms->stepsPerFrame;
- /* not too nice hack, but collisions need this correction -jahka */
- clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale;
-
// collisions
// itstart();
@@ -1618,7 +1614,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
// call collision function
// TODO: check if "step" or "step+dt" is correct - dg
- result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
+ result = cloth_bvh_objcollision(ob, clmd, step, dt);
// correct velocity again, just to be sure we had to change it due to adaptive collisions
for(i = 0; i < numverts; i++)
@@ -1641,9 +1637,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
}
}
- /* restore original stepsPerFrame */
- clmd->sim_parms->stepsPerFrame = temp;
-
// X = Xnew;
cp_lfvector(id->X, id->Xnew, numverts);
@@ -1661,6 +1654,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
}
+
}
else
{
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 57b88bb0b3f..b410c521dea 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -615,7 +615,7 @@ int find_material_index(Object *ob, Material *ma)
return 0;
}
-void object_add_material_slot(Object *ob)
+void new_material_to_objectdata(Object *ob)
{
Material *ma;
@@ -854,7 +854,7 @@ void automatname(Material *ma)
}
-void object_remove_material_slot(Object *ob)
+void delete_material_index(Object *ob)
{
Material *mao, ***matarar;
Object *obt;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 80a9f173d6a..bf3d27cafbf 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -3543,7 +3543,7 @@ static void displaceModifier_updateDepgraph(
}
}
-static void validate_layer_name(const CustomData *data, int type, char *name, char *outname)
+static void validate_layer_name(const CustomData *data, int type, char *name)
{
int index = -1;
@@ -3556,10 +3556,8 @@ static void validate_layer_name(const CustomData *data, int type, char *name, ch
* deleted, so assign the active layer to name
*/
index = CustomData_get_active_layer_index(data, CD_MTFACE);
- strcpy(outname, data->layers[index].name);
+ strcpy(name, data->layers[index].name);
}
- else
- strcpy(outname, name);
}
static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
@@ -3585,11 +3583,12 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
int numFaces = dm->getNumFaces(dm);
- char uvname[32];
MTFace *tf;
- validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+ validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
+
+ tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ dmd->uvlayer_name);
/* verts are given the UV from the first face that uses them */
for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@ -3885,7 +3884,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int num_projectors = 0;
float aspect;
- char uvname[32];
if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty;
else aspect = 1.0f;
@@ -3900,11 +3898,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
/* make sure we're using an existing layer */
- validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
+ validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
/* make sure we are not modifying the original UV layer */
tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
- CD_MTFACE, uvname);
+ CD_MTFACE,
+ umd->uvlayer_name);
numVerts = dm->getNumVerts(dm);
@@ -5186,11 +5185,12 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
int numFaces = dm->getNumFaces(dm);
- char uvname[32];
MTFace *tf;
- validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+ validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
+
+ tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ wmd->uvlayer_name);
/* verts are given the UV from the first face that uses them */
for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@ -6295,9 +6295,6 @@ CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData
MTex *mtex;
int i;
- if(!psmd->psys->part)
- return 0;
-
ma= give_current_material(ob, psmd->psys->part->omat);
if(ma) {
for(i=0; i<MAX_MTEX; i++) {
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 5def910ddef..b1387281cf5 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -1270,10 +1270,8 @@ void multires_free(Multires *mr)
if(lvl) {
CustomData_free(&mr->vdata, lvl->totvert);
CustomData_free(&mr->fdata, lvl->totface);
- if(mr->edge_flags)
- MEM_freeN(mr->edge_flags);
- if(mr->edge_creases)
- MEM_freeN(mr->edge_creases);
+ MEM_freeN(mr->edge_flags);
+ MEM_freeN(mr->edge_creases);
}
while(lvl) {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 2474053298d..34e69b2d736 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -222,34 +222,6 @@ short psys_get_current_num(Object *ob)
return i;
}
-void psys_set_current_num(Object *ob, int index)
-{
- ParticleSystem *psys;
- short i;
-
- if(ob==0) return;
-
- for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) {
- if(i == index - 1)
- psys->flag |= PSYS_CURRENT;
- else
- psys->flag &= ~PSYS_CURRENT;
- }
-}
-Object *psys_find_object(Scene *scene, ParticleSystem *psys)
-{
- Base *base = scene->base.first;
- ParticleSystem *tpsys;
-
- for(base = scene->base.first; base; base = base->next) {
- for(tpsys = base->object->particlesystem.first; psys; psys=psys->next) {
- if(tpsys == psys)
- return base->object;
- }
- }
-
- return NULL;
-}
/* change object's active particle system */
void psys_change_act(void *ob_v, void *act_v)
{
@@ -321,7 +293,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
ParticleSystemModifierData *psmd;
Mesh *me;
- if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part)
+ if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE)
return 0;
if(ob->type == OB_MESH) {
@@ -892,7 +864,7 @@ static void weighted_particle_vector(float *v1, float *v2, float *v3, float *v4,
vec[1]= weights[0]*v1[1] + weights[1]*v2[1] + weights[2]*v3[1] + weights[3]*v4[1];
vec[2]= weights[0]*v1[2] + weights[1]*v2[2] + weights[2]*v3[2] + weights[3]*v4[2];
}
-void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
+static void interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
{
float t[4];
@@ -2597,7 +2569,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
}
/* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
- psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+ interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, &result, 0);
@@ -2929,61 +2901,6 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa
/************************************************/
/* ParticleSettings handling */
/************************************************/
-void object_add_particle_system_slot(Scene *scene, Object *ob)
-{
- ParticleSystem *psys;
- ModifierData *md;
- ParticleSystemModifierData *psmd;
-
- if(!ob || ob->type != OB_MESH)
- return;
-
- psys = ob->particlesystem.first;
- for(; psys; psys=psys->next)
- psys->flag &= ~PSYS_CURRENT;
-
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
- psys->pointcache = BKE_ptcache_add();
- BLI_addtail(&ob->particlesystem, psys);
-
- psys->part = psys_new_settings("PSys", NULL);
-
- md= modifier_new(eModifierType_ParticleSystem);
- sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
- psmd= (ParticleSystemModifierData*) md;
- psmd->psys=psys;
- BLI_addtail(&ob->modifiers, md);
-
- psys->totpart=0;
- psys->flag = PSYS_ENABLED|PSYS_CURRENT;
- psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0);
-
- DAG_scene_sort(scene);
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-}
-void object_remove_particle_system_slot(Scene *scene, Object *ob)
-{
- ParticleSystem *psys = psys_get_current(ob);
- ParticleSystemModifierData *psmd;
-
- if(!psys)
- return;
-
- /* clear modifier */
- psmd= psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- /* clear particle system */
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob,psys);
-
- if(ob->particlesystem.first)
- ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
-
- DAG_scene_sort(scene);
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-}
static void default_particle_settings(ParticleSettings *part)
{
int i;
@@ -3070,9 +2987,6 @@ ParticleSettings *psys_new_settings(char *name, Main *main)
{
ParticleSettings *part;
- if(main==NULL)
- main = G.main;
-
part= alloc_libblock(&main->particle, ID_PA, name);
default_particle_settings(part);
@@ -3148,6 +3062,7 @@ void make_local_particlesettings(ParticleSettings *part)
}
}
}
+
void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc)
{
Base *base = scene->base.first;
@@ -3580,7 +3495,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
}
- psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+ interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, state, 1);
@@ -3787,8 +3702,6 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
return 0;
-
- state->time = MIN2(state->time, pa->dietime);
}
if(psys->flag & PSYS_KEYED){
@@ -3863,7 +3776,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec);
- psys_interpolate_particle(-1, keys, keytime, state, 1);
+ interpolate_particle(-1, keys, keytime, state, 1);
/* convert back to real velocity */
VecMulf(state->vel, frs_sec / dfra);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 591b6ca9be5..52f13eeadb8 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -29,8 +29,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
-
#include <stdlib.h>
#include <math.h>
#include <string.h>
@@ -106,8 +104,7 @@ static int get_current_display_percentage(ParticleSystem *psys)
{
ParticleSettings *part=psys->part;
- if(psys->renderdata || (part->child_nbr && part->childtype)
- || (psys->pointcache->flag & PTCACHE_BAKING))
+ if(psys->renderdata || (part->child_nbr && part->childtype))
return 100;
if(part->phystype==PART_PHYS_KEYED){
@@ -2198,91 +2195,57 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o
/************************************************/
/* Point Cache */
/************************************************/
-void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
-{
- ParticleSettings *part = psys->part;
-
- *sfra = MAX2(1, (int)part->sta);
- *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
-}
-static void particle_write_state(int index, ParticleSystem *psys, float *data)
-{
- memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
-}
-static void particle_read_state(int index, void *psys_ptr, float *data)
-{
- ParticleSystem *psys= psys_ptr;
- ParticleData *pa = psys->particles + index;
- ParticleKey *key = (ParticleKey *)data;
-
- if(key->time > pa->state.time)
- copy_particle_key(&pa->prev_state, &pa->state, 1);
-
- copy_particle_key(&pa->state, key, 1);
-}
-static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
-{
- ParticleSystem *psys= psys_ptr;
- ParticleData *pa = psys->particles + index;
- ParticleKey keys[4];
- float dfra, cfra1f = (float)cfra1, cfra2f(float);
-
- cfra = MIN2(cfra, pa->dietime);
- cfra1 = MIN2(cfra1, pa->dietime);
- cfra2 = MIN2(cfra2, pa->dietime);
-
- keys[1] = *((ParticleKey*)data1);
- keys[2] = *((ParticleKey*)data2);
-
- if(cfra1 == cfra2) {
- copy_particle_key(&pa->state, &keys[1], 1);
- return;
- }
-
- dfra = cfra2 - cfra1;
-
- VecMulf(keys[1].vel, dfra / frs_sec);
- VecMulf(keys[2].vel, dfra / frs_sec);
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
-
- VecMulf(pa->state.vel, frs_sec / dfra);
-
- pa->state.time = cfra;
-}
static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
{
- PTCacheWriter writer;
PTCacheID pid;
+ PTCacheFile *pf;
+ ParticleData *pa;
+ int i, totpart= psys->totpart;
- BKE_ptcache_id_from_particles(&pid, ob, psys);
+ if(totpart == 0)
+ return;
- writer.calldata = psys;
- writer.cfra = cfra;
- writer.set_elem = particle_write_state;
- writer.pid = &pid;
- writer.totelem = psys->totpart;
+ BKE_ptcache_id_from_particles(&pid, ob, psys);
+ pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, cfra);
+ if(!pf)
+ return;
- BKE_ptcache_write_cache(&writer);
+ /* assuming struct consists of tightly packed floats */
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++)
+ BKE_ptcache_file_write_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float));
+
+ BKE_ptcache_file_close(pf);
}
-static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
+static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra)
{
- PTCacheReader reader;
PTCacheID pid;
-
+ PTCacheFile *pf;
+ ParticleData *pa;
+ int i, totpart= psys->totpart;
+
+ if(totpart == 0)
+ return 0;
+
BKE_ptcache_id_from_particles(&pid, ob, psys);
+ pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra);
+ if(!pf)
+ return 0;
- reader.calldata = psys;
- reader.cfra = cfra;
- reader.interpolate_elem = particle_cache_interpolate;
- reader.old_frame = old_frame;
- reader.pid = &pid;
- reader.scene = scene;
- reader.set_elem = particle_read_state;
- reader.totelem = psys->totpart;
+ /* assuming struct consists of tightly packed floats */
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+ if(cfra!=pa->state.time)
+ copy_particle_key(&pa->prev_state,&pa->state,1);
+ if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) {
+ BKE_ptcache_file_close(pf);
+ return 0;
+ }
+ }
+
+ BKE_ptcache_file_close(pf);
- return BKE_ptcache_read_cache(&reader);
+ return 1;
}
/************************************************/
@@ -2409,8 +2372,6 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs
Object *tob;
for(i=0; epsys; epsys=epsys->next,i++){
- if(!psys_check_enabled(ob, epsys))
- continue;
type=0;
if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
epart=epsys->part;
@@ -4124,7 +4085,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
/* main loop: calculate physics for all particles */
for(p=0, pa=psys->particles; p<totpart; p++,pa++){
- if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
+ if(pa->flag & PARS_UNEXIST) continue;
copy_particle_key(&pa->prev_state,&pa->state,1);
@@ -4149,26 +4110,25 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
if(pa->alive==PARS_UNBORN
|| pa->alive==PARS_KILLED
|| ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
- || birthtime >= psys->cfra){
+ || birthtime >= cfra){
reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
}
pa_dfra = dfra;
pa_dtime = dtime;
-
- if(dietime <= cfra && psys->cfra < dietime){
- /* particle dies some time between this and last step */
- pa_dfra = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
- pa_dtime = pa_dfra * timestep;
- pa->alive = PARS_DYING;
- }
- else if(birthtime <= cfra && birthtime >= psys->cfra){
+ if(birthtime <= cfra && birthtime >= psys->cfra){
/* particle is born some time between this and last step*/
pa->alive = PARS_ALIVE;
pa_dfra = cfra - birthtime;
pa_dtime = pa_dfra*timestep;
}
+ else if(dietime <= cfra && psys->cfra < dietime){
+ /* particle dies some time between this and last step */
+ pa_dfra = dietime - psys->cfra;
+ pa_dtime = pa_dfra * timestep;
+ pa->alive = PARS_DYING;
+ }
else if(dietime < cfra){
/* nothing to be done when particle is dead */
}
@@ -4375,7 +4335,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
pa->alive = PARS_UNBORN;
else if(dietime <= cfra){
if(dietime > psys->cfra){
- state.time = dietime;
+ state.time = pa->dietime;
psys_get_particle_state(scene, ob,psys,p,&state,1);
push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
}
@@ -4560,7 +4520,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
int totpart, oldtotpart, totchild, oldtotchild, p;
float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
- int framenr, framedelta, startframe, endframe, old_framenr;
+ int framenr, framedelta, startframe, endframe;
part= psys->part;
cache= psys->pointcache;
@@ -4568,10 +4528,6 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
framenr= (int)scene->r.cfra;
framedelta= framenr - cache->simframe;
- /* set suitable cache range automatically */
- if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
- psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe);
-
BKE_ptcache_id_from_particles(&pid, ob, psys);
BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL);
@@ -4644,13 +4600,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
if(init) {
if(distr) {
- if(alloc) {
+ if(alloc)
realloc_particles(ob, psys, totpart);
- if(usecache)
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
- }
-
distribute_particles(scene, ob, psys, part->from);
if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
@@ -4664,11 +4616,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
free_keyed_keys(psys);
initialize_all_particles(ob, psys, psmd);
-
- if(alloc) {
+ if(alloc)
reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart);
- }
}
/* flag for possible explode modifiers after this system */
@@ -4677,59 +4627,46 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
/* try to read from the cache */
if(usecache) {
- int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
-
- if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
- //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
- // psys_count_keyed_targets(ob,psys);
- // set_keyed_keys(scene, ob, psys);
- //}
+ if(get_particles_from_cache(ob, psys, framenr)) {
+ if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
+ psys_count_keyed_targets(ob,psys);
+ set_keyed_keys(scene, ob, psys);
+ }
cached_step(scene, ob, psmd, psys, cfra);
psys->cfra=cfra;
psys->recalc = 0;
- //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
- // psys_update_path_cache(scene, ob, psmd, psys, framenr);
- //}
+ if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
+ psys_update_path_cache(scene, ob, psmd, psys, framenr);
+ }
cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID;
- if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- write_particles_to_cache(ob, psys, cfra);
-
return;
}
- else if(result==PTCACHE_READ_OLD) {
- /* set old cfra */
- psys->cfra = (float)old_framenr;
-
- for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
- /* update alive status */
- if(pa->time > psys->cfra)
- pa->alive = PARS_UNBORN;
- else if(pa->dietime <= psys->cfra)
- pa->alive = PARS_DEAD;
- else
- pa->alive = PARS_ALIVE;
- }
- }
else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
psys_reset(psys, PSYS_RESET_CACHE_MISS);
psys->cfra=cfra;
psys->recalc = 0;
return;
}
+
+ if(framenr != startframe && framedelta != 1) {
+ psys_reset(psys, PSYS_RESET_CACHE_MISS);
+ psys->cfra = cfra;
+ psys->recalc = 0;
+ return;
+ }
}
else {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
- cache->last_exact= 0;
}
/* if on second frame, write cache for first frame */
- if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
+ if(usecache && framenr == startframe+1)
write_particles_to_cache(ob, psys, startframe);
if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED)
@@ -4831,7 +4768,8 @@ static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys)
static int hair_needs_recalc(ParticleSystem *psys)
{
if((psys->flag & PSYS_EDITED)==0 &&
- ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) {
+ ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_REDO)) {
+ psys->recalc &= ~PSYS_RECALC_REDO;
return 1;
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 64473d07151..b00755f7135 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -51,11 +51,9 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_scene.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
/* needed for directory lookup */
#ifndef WIN32
@@ -215,29 +213,21 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho
filename[0] = '\0';
newname = filename;
- if (!G.relbase_valid) return 0; /* save blend file before using disk pointcache */
+ /*if (!G.relbase_valid) return 0; *//* save blend file before using pointcache */
/* start with temp dir */
if (do_path) {
len = ptcache_path(pid, filename);
newname += len;
}
- if(strcmp(pid->cache->name, "")==0) {
- idname = (pid->ob->id.name+2);
- /* convert chars to hex so they are always a valid filename */
- while('\0' != *idname) {
- snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
- newname+=2;
- len += 2;
- }
+ idname = (pid->ob->id.name+2);
+ /* convert chars to hex so they are always a valid filename */
+ while('\0' != *idname) {
+ snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
+ newname+=2;
+ len += 2;
}
- else {
- int temp = strlen(pid->cache->name);
- strcpy(newname, pid->cache->name);
- newname+=temp;
- len += temp;
- }
-
+
if (do_ext) {
snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
len += 16;
@@ -257,7 +247,7 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
return NULL;
- if (!G.relbase_valid) return NULL; /* save blend file before using disk pointcache */
+ /*if (!G.relbase_valid) return NULL; *//* save blend file before using pointcache */
BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
@@ -296,427 +286,6 @@ int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot)
return (fwrite(f, sizeof(float), tot, pf->fp) == tot);
}
-static int ptcache_pid_elemsize(PTCacheID *pid)
-{
- if(pid->type==PTCACHE_TYPE_SOFTBODY)
- return 0; // TODO
- else if(pid->type==PTCACHE_TYPE_PARTICLES)
- return sizeof(ParticleKey);
- else if(pid->type==PTCACHE_TYPE_CLOTH)
- return 9 * sizeof(float);
-
- return 0;
-}
-static int ptcache_pid_totelem(PTCacheID *pid)
-{
- if(pid->type==PTCACHE_TYPE_SOFTBODY)
- return 0; // TODO
- else if(pid->type==PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys = pid->data;
- return psys->totpart;
- }
- else if(pid->type==PTCACHE_TYPE_CLOTH)
- return 0; // TODO
-
- return 0;
-}
-
-void BKE_ptcache_update_info(PTCacheID *pid)
-{
- PointCache *cache = pid->cache;
- int totframes = 0;
- char mem_info[64];
-
- if(cache->flag & PTCACHE_DISK_CACHE) {
- int cfra = cache->startframe;
-
- for(; cfra<=cache->endframe; cfra++) {
- if(BKE_ptcache_id_exist(pid, cfra))
- totframes++;
- }
-
- sprintf(mem_info, "%i frames on disk", totframes);
- }
- else {
- PTCacheMem *pm = cache->mem_cache.first;
- float framesize = 0.0f, bytes = 0.0f;
- int mb;
-
- if(pm)
- framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint;
-
- for(; pm; pm=pm->next)
- totframes++;
-
- bytes = totframes * framesize;
-
- mb = (bytes > 1024.0f * 1024.0f);
-
- sprintf(mem_info, "%i frames in memory (%.1f %s)",
- totframes,
- bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
- mb ? "Mb" : "kb");
- }
-
- if(cache->flag & PTCACHE_OUTDATED) {
- sprintf(cache->info, "%s, cache is outdated!", mem_info);
- }
- else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
- sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
- }
- else
- sprintf(cache->info, "%s.", mem_info);
-}
-/* reads cache from disk or memory */
-/* possible to get old or interpolated result */
-int BKE_ptcache_read_cache(PTCacheReader *reader)
-{
- PTCacheID *pid = reader->pid;
- PTCacheFile *pf=NULL, *pf2=NULL;
- PTCacheMem *pm=NULL, *pm2=NULL;
- int totelem = reader->totelem;
- float cfra = reader->cfra;
- int cfrai = (int)cfra;
- int elemsize = ptcache_pid_elemsize(pid);
- int i, incr = elemsize / sizeof(float);
- float frs_sec = reader->scene->r.frs_sec;
- int cfra1=0, cfra2;
- int ret = 0;
-
- if(totelem == 0)
- return 0;
-
-
- /* first check if we have the actual frame cached */
- if(cfra == (float)cfrai) {
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- }
- else {
- pm = pid->cache->mem_cache.first;
-
- for(; pm; pm=pm->next) {
- if(pm->frame == cfrai)
- break;
- }
- }
- }
-
- /* if found, use exact frame */
- if(pf || pm) {
- float *data;
-
- if(pm)
- data = pm->data;
- else
- data = MEM_callocN(elemsize, "pointcache read data");
-
- for(i=0; i<totelem; i++) {
- if(pf) {
- if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
- BKE_ptcache_file_close(pf);
- MEM_freeN(data);
- return 0;
- }
-
- reader->set_elem(i, reader->calldata, data);
- }
- else {
- reader->set_elem(i, reader->calldata, data);
- data += incr;
- }
- }
-
- if(pf) {
- BKE_ptcache_file_close(pf);
- MEM_freeN(data);
- }
-
- ret = PTCACHE_READ_EXACT;
- }
-
- if(ret)
- ;
- /* no exact cache frame found so try to find cached frames around cfra */
- else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf=NULL;
- while(cfrai > pid->cache->startframe && !pf) {
- cfrai--;
- pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra1 = cfrai;
- }
-
- if(reader->old_frame)
- *(reader->old_frame) = cfrai;
-
- cfrai = (int)cfra;
- while(cfrai < pid->cache->endframe && !pf2) {
- cfrai++;
- pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra2 = cfrai;
- }
- }
- else if(pid->cache->mem_cache.first){
- pm = pid->cache->mem_cache.first;
-
- while(pm->next && pm->next->frame < cfra)
- pm= pm->next;
-
- if(pm) {
- if(reader->old_frame)
- *(reader->old_frame) = pm->frame;
- cfra1 = pm->frame;
- }
-
- pm2 = pid->cache->mem_cache.last;
-
- if(pm2 && pm2->frame < cfra)
- pm2 = NULL;
- else {
- while(pm2->prev && pm2->prev->frame > cfra)
- pm2= pm2->prev;
-
- if(pm2)
- cfra2 = pm2->frame;
- }
- }
-
- if(ret)
- ;
- else if((pf && pf2) || (pm && pm2)) {
- /* interpolate from nearest frames if cache isn't outdated */
- float *data1, *data2;
-
- if(pm) {
- data1 = pm->data;
- data2 = pm2->data;
- }
- else {
- data1 = MEM_callocN(elemsize, "pointcache read data1");
- data2 = MEM_callocN(elemsize, "pointcache read data2");
- }
-
- for(i=0; i<totelem; i++) {
- if(pf && pf2) {
- if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
- BKE_ptcache_file_close(pf);
- BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- return 0;
- }
- if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
- BKE_ptcache_file_close(pf);
- BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- return 0;
- }
- reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
- }
- else {
- reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
- data1 += incr;
- data2 += incr;
- }
- }
-
- if(pf) {
- BKE_ptcache_file_close(pf);
- BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- }
-
- ret = PTCACHE_READ_INTERPOLATED;
- }
- else if(pf || pm) {
- /* use last valid cache frame */
- float *data;
-
- /* don't read cache if allready simulated past cached frame */
- if(cfra1 && cfra1 <= pid->cache->simframe) {
- if(pf)
- BKE_ptcache_file_close(pf);
- if(pf2)
- BKE_ptcache_file_close(pf2);
-
- return 0;
- }
-
- if(pm)
- data = pm->data;
- else
- data = MEM_callocN(elemsize, "pointcache read data");
-
- for(i=0; i<totelem; i++) {
- if(pf) {
- if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
- BKE_ptcache_file_close(pf);
- if(pf2)
- BKE_ptcache_file_close(pf2);
- return 0;
- }
- reader->set_elem(i, reader->calldata, data);
- }
- else {
- reader->set_elem(i, reader->calldata, data);
- data += incr;
- }
- }
-
- if(pf) {
- BKE_ptcache_file_close(pf);
- MEM_freeN(data);
- }
- if(pf2)
- BKE_ptcache_file_close(pf2);
-
- ret = PTCACHE_READ_OLD;
- }
-
- if(pf)
- BKE_ptcache_file_close(pf);
- if(pf2)
- BKE_ptcache_file_close(pf2);
-
- if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
- /* clear invalid cache frames so that better stuff can be simulated */
- if(pid->cache->flag & PTCACHE_OUTDATED) {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
- }
- else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
- if(cfra <= pid->cache->last_exact)
- pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
- }
- }
-
- return ret;
-}
-/* writes cache to disk or memory */
-int BKE_ptcache_write_cache(PTCacheWriter *writer)
-{
- PointCache *cache = writer->pid->cache;
- PTCacheFile *pf= NULL;
- int elemsize = ptcache_pid_elemsize(writer->pid);
- int i, incr = elemsize / sizeof(float);
- int add = 0, overwrite = 0, ocfra;
- float temp[14];
-
- if(writer->totelem == 0 || writer->cfra <= 0)
- return 0;
-
- if(cache->flag & PTCACHE_DISK_CACHE) {
- /* allways start from scratch on the first frame */
- if(writer->cfra == cache->startframe) {
- BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- add = 1;
- }
- else {
- int cfra = cache->endframe;
- /* find last cached frame */
- while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
- cfra--;
-
- /* find second last cached frame */
- ocfra = cfra-1;
- while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
- ocfra--;
-
- if(writer->cfra > cfra) {
- if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
- overwrite = 1;
- else
- add = 1;
- }
- }
-
- if(add || overwrite) {
- if(overwrite)
- BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
-
- pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
- if(!pf)
- return 0;
-
- for(i=0; i<writer->totelem; i++) {
- writer->set_elem(i, writer->calldata, &temp);
- BKE_ptcache_file_write_floats(pf, &temp, incr);
- }
- }
- }
- else {
- PTCacheMem *pm;
- PTCacheMem *pm2;
- float *pmdata;
-
- pm2 = cache->mem_cache.first;
-
- /* allways start from scratch on the first frame */
- if(writer->cfra == cache->startframe) {
- BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- add = 1;
- }
- else {
- pm2 = cache->mem_cache.last;
-
- if(pm2 && writer->cfra > pm2->frame) {
- if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
- overwrite = 1;
- else
- add = 1;
- }
- }
-
- if(overwrite) {
- pm = cache->mem_cache.last;
- pmdata = pm->data;
-
- for(i=0; i<writer->totelem; i++, pmdata+=incr) {
- writer->set_elem(i, writer->calldata, &temp);
- memcpy(pmdata, &temp, elemsize);
- }
-
- pm->frame = writer->cfra;
- }
- else if(add) {
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
- pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
- pmdata = pm->data;
-
- for(i=0; i<writer->totelem; i++, pmdata+=incr) {
- writer->set_elem(i, writer->calldata, &temp);
- memcpy(pmdata, &temp, elemsize);
- }
-
- pm->frame = writer->cfra;
- pm->totpoint = writer->totelem;
-
- BLI_addtail(&cache->mem_cache, pm);
- }
- }
-
- if(add || overwrite) {
- if(writer->cfra - cache->last_exact == 1
- || writer->cfra == cache->startframe) {
- cache->last_exact = writer->cfra;
- cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
- }
- else
- cache->flag |= PTCACHE_FRAMES_SKIPPED;
- }
-
- if(pf)
- BKE_ptcache_file_close(pf);
-
- BKE_ptcache_update_info(writer->pid);
-
- return 1;
-}
/* youll need to close yourself after!
* mode - PTCACHE_CLEAR_ALL,
@@ -748,116 +317,62 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
case PTCACHE_CLEAR_ALL:
case PTCACHE_CLEAR_BEFORE:
case PTCACHE_CLEAR_AFTER:
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- ptcache_path(pid, path);
-
- len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
-
- dir = opendir(path);
- if (dir==NULL)
- return;
-
- snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
-
- while ((de = readdir(dir)) != NULL) {
- if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
- if (mode == PTCACHE_CLEAR_ALL) {
- pid->cache->last_exact = 0;
- BLI_join_dirfile(path_full, path, de->d_name);
- BLI_delete(path_full, 0, 0);
- } else {
- /* read the number of the file */
- int frame, len2 = strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
+ ptcache_path(pid, path);
+
+ len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
+
+ dir = opendir(path);
+ if (dir==NULL)
+ return;
+
+ snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
+
+ while ((de = readdir(dir)) != NULL) {
+ if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
+ if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ if (mode == PTCACHE_CLEAR_ALL) {
+ BLI_join_dirfile(path_full, path, de->d_name);
+ BLI_delete(path_full, 0, 0);
+ } else {
+ /* read the number of the file */
+ int frame, len2 = strlen(de->d_name);
+ char num[7];
+
+ if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
+ BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
+ frame = atoi(num);
+
+ if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) ||
+ (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) {
- if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) ||
- (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) {
-
- BLI_join_dirfile(path_full, path, de->d_name);
- BLI_delete(path_full, 0, 0);
- }
+ BLI_join_dirfile(path_full, path, de->d_name);
+ BLI_delete(path_full, 0, 0);
}
}
}
}
}
- closedir(dir);
- }
- else {
- PTCacheMem *pm= pid->cache->mem_cache.first;
- PTCacheMem *link= NULL;
-
- if(mode == PTCACHE_CLEAR_ALL) {
- pid->cache->last_exact = 0;
- for(; pm; pm=pm->next)
- MEM_freeN(pm->data);
- BLI_freelistN(&pid->cache->mem_cache);
- } else {
- while(pm) {
- if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
- (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
- link = pm;
- pm = pm->next;
- MEM_freeN(link->data);
- BLI_freelinkN(&pid->cache->mem_cache, link);
- }
- else
- pm = pm->next;
- }
- }
}
+ closedir(dir);
break;
case PTCACHE_CLEAR_FRAME:
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- if(BKE_ptcache_id_exist(pid, cfra)) {
- BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
- BLI_delete(filename, 0, 0);
- }
- }
- else {
- PTCacheMem *pm = pid->cache->mem_cache.first;
-
- for(; pm; pm=pm->next) {
- if(pm->frame == cfra) {
- MEM_freeN(pm->data);
- BLI_freelinkN(&pid->cache->mem_cache, pm);
- break;
- }
- }
- }
+ len = BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
+ BLI_delete(filename, 0, 0);
break;
}
-
- BKE_ptcache_update_info(pid);
}
int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
{
+ char filename[MAX_PTCACHE_FILE];
+
if(!pid->cache)
return 0;
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- char filename[MAX_PTCACHE_FILE];
-
- BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
-
- return BLI_exists(filename);
- }
- else {
- PTCacheMem *pm = pid->cache->mem_cache.first;
+ BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
- for(; pm; pm=pm->next) {
- if(pm->frame==cfra)
- return 1;
- }
- return 0;
- }
+ return BLI_exists(filename);
}
void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
@@ -866,9 +381,6 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
PointCache *cache;
float offset, time, nexttime;
- /* TODO: this has to be sorter out once bsystem_time gets redone, */
- /* now caches can handle interpolating etc. too - jahka */
-
/* time handling for point cache:
* - simulation time is scaled by result of bsystem_time
* - for offsetting time only time offset is taken into account, since
@@ -902,10 +414,10 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
}
}
-int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
+int BKE_ptcache_id_reset(PTCacheID *pid, int mode)
{
PointCache *cache;
- int reset, clear, after;
+ int reset, clear;
if(!pid->cache)
return 0;
@@ -913,17 +425,14 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
cache= pid->cache;
reset= 0;
clear= 0;
- after= 0;
if(mode == PTCACHE_RESET_DEPSGRAPH) {
if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
- if(cache->flag & PTCACHE_QUICK_CACHE)
- clear= 1;
-
- after= 1;
+ reset= 1;
+ clear= 1;
}
-
- cache->flag |= PTCACHE_OUTDATED;
+ else
+ cache->flag |= PTCACHE_OUTDATED;
}
else if(mode == PTCACHE_RESET_BAKED) {
if(!BKE_ptcache_get_continue_physics()) {
@@ -942,9 +451,8 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
}
if(reset) {
- cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
+ cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID);
cache->simframe= 0;
- cache->last_exact= 0;
if(pid->type == PTCACHE_TYPE_CLOTH)
cloth_free_modifier(pid->ob, pid->data);
@@ -955,13 +463,11 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
}
if(clear)
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- else if(after)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
- return (reset || clear || after);
+ return (reset || clear);
}
-int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
+int BKE_ptcache_object_reset(Object *ob, int mode)
{
PTCacheID pid;
ParticleSystem *psys;
@@ -973,7 +479,7 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
if(ob->soft) {
BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
+ reset |= BKE_ptcache_id_reset(&pid, mode);
}
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
@@ -982,23 +488,23 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
if(psys->soft) {
BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
+ reset |= BKE_ptcache_id_reset(&pid, mode);
else
skip = 1;
}
- else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
+ else if((psys->recalc & PSYS_RECALC_RESET)==0)
skip = 1;
if(skip == 0) {
BKE_ptcache_id_from_particles(&pid, ob, psys);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
+ reset |= BKE_ptcache_id_reset(&pid, mode);
}
}
for(md=ob->modifiers.first; md; md=md->next) {
if(md->type == eModifierType_Cloth) {
BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
+ reset |= BKE_ptcache_id_reset(&pid, mode);
}
}
@@ -1058,7 +564,7 @@ void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
if(CONTINUE_PHYSICS == 0) {
for(ob=G.main->object.first; ob; ob=ob->id.next)
- if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
+ if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_OUTDATED))
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
}
@@ -1078,21 +584,12 @@ PointCache *BKE_ptcache_add()
cache= MEM_callocN(sizeof(PointCache), "PointCache");
cache->startframe= 1;
cache->endframe= 250;
- cache->step= 10;
return cache;
}
void BKE_ptcache_free(PointCache *cache)
{
- PTCacheMem *pm = cache->mem_cache.first;
- if(pm) {
- for(; pm; pm=pm->next)
- MEM_freeN(pm->data);
-
- BLI_freelistN(&cache->mem_cache);
- }
-
MEM_freeN(cache);
}
@@ -1108,276 +605,3 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
return ncache;
}
-
-
-/* Baking */
-static int count_quick_cache(Scene *scene, int *quick_step)
-{
- Base *base = scene->base.first;
- PTCacheID *pid;
- ListBase pidlist;
- int autocache_count= 0;
-
- for(base = scene->base.first; base; base = base->next) {
- if(base->object) {
- BKE_ptcache_ids_from_object(&pidlist, base->object);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- if((pid->cache->flag & PTCACHE_BAKED)
- || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
- continue;
-
- if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
- if(!autocache_count)
- *quick_step = pid->cache->step;
- else
- *quick_step = MIN2(*quick_step, pid->cache->step);
-
- autocache_count++;
- }
- }
-
- BLI_freelistN(&pidlist);
- }
- }
-
- return autocache_count;
-}
-void BKE_ptcache_quick_cache_all(Scene *scene)
-{
- PTCacheBaker baker;
-
- baker.bake=0;
- baker.break_data=NULL;
- baker.break_test=NULL;
- baker.pid=NULL;
- baker.progressbar=NULL;
- baker.progresscontext=NULL;
- baker.render=0;
- baker.scene=scene;
-
- if(count_quick_cache(scene, &baker.quick_step))
- BKE_ptcache_make_cache(&baker);
-}
-
-/* if bake is not given run simulations to current frame */
-void BKE_ptcache_make_cache(PTCacheBaker* baker)
-{
- Scene *scene = baker->scene;
- Base *base;
- ListBase pidlist;
- PTCacheID *pid = baker->pid;
- PointCache *cache;
- float frameleno = scene->r.framelen;
- int cfrao = CFRA;
- int startframe = MAXFRAME;
- int endframe = CFRA;
- int bake = baker->bake;
- int render = baker->render;
- int step = baker->quick_step;
-
- G.afbreek = 0;
-
- /* set caches to baking mode and figure out start frame */
- if(pid) {
- /* cache/bake a single object */
- cache = pid->cache;
- if((cache->flag & PTCACHE_BAKED)==0) {
- if(pid->type==PTCACHE_TYPE_PARTICLES)
- psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
-
- if(bake || cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- startframe = MAX2(cache->last_exact, cache->startframe);
-
- if(bake) {
- endframe = cache->endframe;
- cache->flag |= PTCACHE_BAKING;
- }
- else {
- endframe = MIN2(endframe, cache->endframe);
- }
-
- cache->flag &= ~PTCACHE_BAKED;
- }
- }
- else for(base=scene->base.first; base; base= base->next) {
- /* cache/bake everything in the scene */
- BKE_ptcache_ids_from_object(&pidlist, base->object);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- cache = pid->cache;
- if((cache->flag & PTCACHE_BAKED)==0) {
- if(pid->type==PTCACHE_TYPE_PARTICLES)
- psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
-
- if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
- && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- startframe = MIN2(startframe, cache->startframe);
-
- if(bake || render) {
- cache->flag |= PTCACHE_BAKING;
-
- if(bake)
- endframe = MAX2(endframe, cache->endframe);
- }
-
- cache->flag &= ~PTCACHE_BAKED;
-
- }
- }
- BLI_freelistN(&pidlist);
- }
-
- CFRA= startframe;
- scene->r.framelen = 1.0;
-
- for(; CFRA <= endframe; CFRA+=step) {
- float prog;
-
- if(bake)
- prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe));
- else
- prog = CFRA;
-
- /* NOTE: baking should not redraw whole ui as this slows things down */
- if(baker->progressbar)
- baker->progressbar(baker->progresscontext, prog);
-
- scene_update_for_newframe(scene, scene->lay);
-
- /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
- if(baker->break_test && baker->break_test(baker->break_data))
- break;
- }
-
- /* clear baking flag */
- if(pid) {
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
- cache->flag |= PTCACHE_SIMULATION_VALID;
- if(bake)
- cache->flag |= PTCACHE_BAKED;
- }
- else for(base=scene->base.first; base; base= base->next) {
- BKE_ptcache_ids_from_object(&pidlist, base->object);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- cache = pid->cache;
-
- if(step > 1)
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
- else
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
-
- cache->flag |= PTCACHE_SIMULATION_VALID;
-
- if(bake)
- cache->flag |= PTCACHE_BAKED;
- }
- BLI_freelistN(&pidlist);
- }
-
- scene->r.framelen = frameleno;
- CFRA = cfrao;
- scene_update_for_newframe(scene, scene->lay);
-
- /* TODO: call redraw all windows somehow */
-}
-
-void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
- PointCache *cache = pid->cache;
- PTCacheFile *pf;
- PTCacheMem *pm;
- int totelem=0;
- int float_count=0;
- int tot;
- int last_exact = cache->last_exact;
-
- if (!G.relbase_valid){
- cache->flag &= ~PTCACHE_DISK_CACHE;
- return;
- }
-
- totelem = ptcache_pid_totelem(pid);
- float_count = ptcache_pid_elemsize(pid) / sizeof(float);
-
- if(totelem==0 || float_count==0)
- return;
-
- tot = totelem*float_count;
-
- /* MEM -> DISK */
- if(cache->flag & PTCACHE_DISK_CACHE) {
- pm = cache->mem_cache.first;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- for(; pm; pm=pm->next) {
- pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
-
- if(pf) {
- if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) {
- printf("Error writing to disk cache\n");
-
- cache->flag &= ~PTCACHE_DISK_CACHE;
-
- BKE_ptcache_file_close(pf);
- return;
- }
- BKE_ptcache_file_close(pf);
- }
- else
- printf("Error creating disk cache file\n");
- }
-
- cache->flag &= ~PTCACHE_DISK_CACHE;
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- cache->flag |= PTCACHE_DISK_CACHE;
- }
- /* DISK -> MEM */
- else {
- int cfra;
- int sfra = cache->startframe;
- int efra = cache->endframe;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- for(cfra=sfra; cfra <= efra; cfra++) {
- pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
-
- if(pf) {
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
- pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data");
-
- if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
- printf("Error reading from disk cache\n");
-
- cache->flag |= PTCACHE_DISK_CACHE;
-
- MEM_freeN(pm->data);
- MEM_freeN(pm);
- BKE_ptcache_file_close(pf);
- return;
- }
-
- pm->frame = cfra;
- pm->totpoint = totelem;
-
- BLI_addtail(&pid->cache->mem_cache, pm);
-
- BKE_ptcache_file_close(pf);
- }
- }
-
- cache->flag |= PTCACHE_DISK_CACHE;
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- cache->flag &= ~PTCACHE_DISK_CACHE;
- }
-
- cache->last_exact = last_exact;
-
- BKE_ptcache_update_info(pid);
-}
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 116fd069948..1d97eccb9f3 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: report.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 23da5c66850..156bdae9b00 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -142,6 +142,8 @@ void free_scene(Scene *sce)
BLI_freelistN(&sce->base);
seq_free_editing(sce->ed);
+ if(sce->radio) MEM_freeN(sce->radio);
+ sce->radio= 0;
#ifndef DISABLE_PYTHON
BPY_free_scriptlink(&sce->scriptlink);
@@ -203,6 +205,9 @@ Scene *add_scene(char *name)
sce= alloc_libblock(&G.main->scene, ID_SCE, name);
sce->lay= 1;
+ sce->selectmode= SCE_SELECT_VERTEX;
+ sce->editbutsize= 0.1;
+ sce->autokey_mode= U.autokey_mode;
sce->r.mode= R_GAMMA;
sce->r.cfra= 1;
@@ -272,10 +277,6 @@ Scene *add_scene(char *name)
sce->toolsettings->select_thresh= 0.01f;
sce->toolsettings->jointrilimit = 0.8f;
- sce->toolsettings->selectmode= SCE_SELECT_VERTEX;
- sce->toolsettings->normalsize= 0.1;
- sce->toolsettings->autokey_mode= U.autokey_mode;
-
sce->toolsettings->skgen_resolution = 100;
sce->toolsettings->skgen_threshold_internal = 0.01f;
sce->toolsettings->skgen_threshold_external = 0.01f;
diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c
index 7fc262b4796..bb0665a5b0f 100644
--- a/source/blender/blenkernel/intern/sequence.c
+++ b/source/blender/blenkernel/intern/sequence.c
@@ -1,5 +1,5 @@
/**
-* $Id$
+* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index d0b106b59c3..d2fb62141de 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -26,7 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*
- * $Id$
+ * $Id: $
*/
#ifndef BLI_LISTBASE_H
diff --git a/source/blender/blenlib/BLI_noise.h b/source/blender/blenlib/BLI_noise.h
index 0886eb3a8a5..9f72c5e7b54 100644
--- a/source/blender/blenlib/BLI_noise.h
+++ b/source/blender/blenlib/BLI_noise.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index c36a41af84b..c7026b21494 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/BLI_storage.h b/source/blender/blenlib/BLI_storage.h
index fa44bb36e15..d7bf3bd13f8 100644
--- a/source/blender/blenlib/BLI_storage.h
+++ b/source/blender/blenlib/BLI_storage.h
@@ -25,20 +25,15 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
#ifndef BLI_STORAGE_H
#define BLI_STORAGE_H
-/* NOTE: these have to be defined before including unistd.h! */
#ifndef __APPLE__
#ifndef WIN32
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
+#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#endif
#endif
-#endif
struct direntry;
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index bf93dc19cc5..4e5bf650196 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -26,7 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*
- * $Id$
+ * $Id: $
*/
#ifndef BLI_STRING_H
diff --git a/source/blender/blenlib/intern/dynamiclist.c b/source/blender/blenlib/intern/dynamiclist.c
index 4fe654cffb6..fbb87124bba 100644
--- a/source/blender/blenlib/intern/dynamiclist.c
+++ b/source/blender/blenlib/intern/dynamiclist.c
@@ -3,7 +3,7 @@
* various string, file, list operations.
*
*
- * $Id$
+ * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/intern/dynamiclist.h b/source/blender/blenlib/intern/dynamiclist.h
index e8c93fbcf23..aba3eda0696 100644
--- a/source/blender/blenlib/intern/dynamiclist.h
+++ b/source/blender/blenlib/intern/dynamiclist.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BLI_dynamiclist.h 13161 2008-01-07 19:13:47Z hos $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 1064c8ac1bf..e0fd5c37494 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -3,7 +3,7 @@
* various string, file, list operations.
*
*
- * $Id$
+ * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
index 269e674a62f..39d38e4cf3a 100644
--- a/source/blender/blenlib/intern/psfont.c
+++ b/source/blender/blenlib/intern/psfont.c
@@ -837,7 +837,7 @@ static int decodetype1(PackedFile * pf, char *outname)
while(newfgets(oneline, LINELEN, pf)) {
hptr = (char *)oneline;
while(*hptr) {
- if(hextab[(int)*hptr] != NOTHEX)
+ if(hextab[*hptr] != NOTHEX)
hexdat[hexbytes++] = *hptr;
hptr++;
}
@@ -853,7 +853,7 @@ static int decodetype1(PackedFile * pf, char *outname)
bptr = bindat;
c = datbytes;
while(c--) {
- *bptr++ = (hextab[(int)hptr[0]]<<4)+hextab[(int)hptr[1]];
+ *bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
hptr += 2;
}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 0ae17a13e43..688a4ab901b 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -62,6 +62,13 @@
#include <sys/vfs.h>
#endif
+#ifdef __BeOS
+struct statfs {
+ int f_bsize;
+ int f_bfree;
+};
+#endif
+
#ifdef __APPLE__
/* For statfs */
#include <sys/param.h>
@@ -70,7 +77,7 @@
#include <fcntl.h>
-#if !defined(WIN32)
+#if !defined(__BeOS) && !defined(WIN32)
#include <sys/mtio.h> /* tape comando's */
#endif
#include <string.h> /* strcpy etc.. */
@@ -194,6 +201,9 @@ double BLI_diskfree(char *dir)
#if defined (__FreeBSD__) || defined (linux) || defined (__OpenBSD__) || defined (__APPLE__)
if (statfs(name, &disk)) return(-1);
#endif
+#ifdef __BeOS
+ return -1;
+#endif
#if defined (__sun__) || defined (__sun) || defined (__sgi)
if (statvfs(name, &disk)) return(-1);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 4cd04aa232c..fa4bcbc26bc 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -3,7 +3,7 @@
* various string, file, list operations.
*
*
- * $Id$
+ * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index 26f4c2dd415..df4ad4e7c75 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -737,7 +737,10 @@ void BLI_splitdirstring(char *di, char *fi)
}
char *BLI_gethome(void) {
- #if !defined(WIN32)
+ #ifdef __BeOS
+ return "/boot/home/"; /* BeOS 4.5: doubleclick at icon doesnt give home env */
+
+ #elif !defined(WIN32)
return getenv("HOME");
#else /* Windows */
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 1f276913ea8..0c8b8a6b31d 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -32,8 +32,6 @@
#include <config.h>
#endif
-#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
-
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 441e8aff2d6..1502b475350 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2878,16 +2878,6 @@ static void direct_link_material(FileData *fd, Material *ma)
static void direct_link_pointcache(FileData *fd, PointCache *cache)
{
- if((cache->flag & PTCACHE_DISK_CACHE)==0) {
- PTCacheMem *pm;
-
- link_list(fd, &cache->mem_cache);
-
- pm = cache->mem_cache.first;
-
- for(; pm; pm=pm->next)
- pm->data = newdataadr(fd, pm->data);
- }
cache->flag &= ~(PTCACHE_SIMULATION_VALID|PTCACHE_BAKE_EDIT_ACTIVE);
cache->simframe= 0;
}
@@ -2899,9 +2889,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
part= main->particle.first;
while(part) {
if(part->id.flag & LIB_NEEDLINK) {
- if (part->adt) lib_link_animdata(fd, &part->id, part->adt);
part->ipo= newlibadr_us(fd, part->id.lib, part->ipo); // XXX depreceated - old animation system
-
part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
@@ -2914,7 +2902,6 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
{
- part->adt= newdataadr(fd, part->adt);
part->pd= newdataadr(fd, part->pd);
part->pd2= newdataadr(fd, part->pd2);
}
@@ -3155,8 +3142,10 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface);
- mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags);
- mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases);
+ if(!mesh->mr->edge_flags)
+ mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
+ if(!mesh->mr->edge_creases)
+ mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases");
mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
@@ -3944,6 +3933,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_keyingsets(fd, &sce->keyingsets);
sce->basact= newdataadr(fd, sce->basact);
+
+ sce->radio= newdataadr(fd, sce->radio);
sce->toolsettings= newdataadr(fd, sce->toolsettings);
if(sce->toolsettings) {
@@ -7105,14 +7096,22 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(main->versionfile <= 234) {
+ Scene *sce;
World *wo;
bScreen *sc;
+ int set_zbuf_sel=0;
// force sumo engine to be active
for (wo = main->world.first; wo; wo= wo->id.next) {
if(wo->physicsEngine==0) wo->physicsEngine = 2;
}
+ for (sce= main->scene.first; sce; sce= sce->id.next) {
+ if(sce->selectmode==0) {
+ sce->selectmode= SCE_SELECT_VERTEX;
+ set_zbuf_sel= 1;
+ }
+ }
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
@@ -7120,7 +7119,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_VIEW3D) {
View3D *v3d= (View3D *)sl;
- v3d->flag |= V3D_ZBUF_SELECT;
+ if(set_zbuf_sel) v3d->flag |= V3D_ZBUF_SELECT;
}
else if(sl->spacetype==SPACE_TEXT) {
SpaceText *st= (SpaceText *)sl;
@@ -7155,10 +7154,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if(main->versionfile <= 236) {
Object *ob;
+ Scene *sce= main->scene.first;
Camera *cam= main->camera.first;
Material *ma;
bScreen *sc;
+ while(sce) {
+ if(sce->editbutsize==0.0) sce->editbutsize= 0.1f;
+
+ sce= sce->id.next;
+ }
while(cam) {
if(cam->ortho_scale==0.0) {
cam->ortho_scale= 256.0f/cam->lens;
@@ -8784,6 +8789,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+ /* autokey mode settings now used from scene, but need to be initialised off userprefs */
+ if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 8)) {
+ Scene *sce;
+
+ for (sce= main->scene.first; sce; sce= sce->id.next) {
+ if (sce->autokey_mode == 0)
+ sce->autokey_mode= U.autokey_mode;
+ }
+ }
if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 9)) {
Lamp *la= main->lamp.first;
@@ -8976,34 +8990,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
- if (main->versionfile < 249 && main->subversionfile < 2) {
- Scene *sce= main->scene.first;
- Sequence *seq;
- Editing *ed;
-
- while(sce) {
- ed= sce->ed;
- if(ed) {
- SEQP_BEGIN(ed, seq) {
- if (seq->strip && seq->strip->proxy){
- if (sce->r.size != 100.0) {
- seq->strip->proxy->size
- = sce->r.size;
- } else {
- seq->strip->proxy->size
- = 25.0;
- }
- seq->strip->proxy->quality =90;
- }
- }
- SEQ_END
- }
-
- sce= sce->id.next;
- }
-
- }
-
if (main->versionfile < 250) {
bScreen *screen;
Scene *scene;
@@ -9012,9 +8998,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Scene *sce;
Tex *tx;
ParticleSettings *part;
- Object *ob;
- PTCacheID *pid;
- ListBase pidlist;
for(screen= main->screen.first; screen; screen= screen->id.next) {
do_versions_windowmanager_2_50(screen);
@@ -9057,7 +9040,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES;
}
- /* particle draw and render types */
+ /* particle settings conversion */
for(part= main->particle.first; part; part= part->id.next) {
if(part->draw_as) {
if(part->draw_as == PART_DRAW_DOT) {
@@ -9073,16 +9056,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
- /* set old pointcaches to have disk cache flag */
- for(ob = main->object.first; ob; ob= ob->id.next) {
-
- BKE_ptcache_ids_from_object(&pidlist, ob);
-
- for(pid=pidlist.first; pid; pid=pid->next)
- pid->cache->flag |= PTCACHE_DISK_CACHE;
-
- BLI_freelistN(&pidlist);
- }
}
/* TODO: should be moved into one of the version blocks once this branch moves to trunk and we can
@@ -9090,8 +9063,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
{
Object *ob;
Material *ma;
- Scene *sce;
- ToolSettings *ts;
int i;
for(ob = main->object.first; ob; ob = ob->id.next) {
@@ -9164,17 +9135,37 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
ma->mode &= ~MA_HALO;
}
}
-
- for(sce = main->scene.first; sce; sce = sce->id.next) {
- ts= sce->toolsettings;
- if(ts->normalsize == 0.0) {
- ts->normalsize= 0.1f;
- ts->selectmode= SCE_SELECT_VERTEX;
- ts->autokey_mode= U.autokey_mode;
+ }
+
+ if (main->versionfile < 249 && main->subversionfile < 2) {
+ Scene *sce= main->scene.first;
+ Sequence *seq;
+ Editing *ed;
+
+ while(sce) {
+ ed= sce->ed;
+ if(ed) {
+ SEQP_BEGIN(ed, seq) {
+ if (seq->strip && seq->strip->proxy){
+ if (sce->r.size != 100.0) {
+ seq->strip->proxy->size
+ = sce->r.size;
+ } else {
+ seq->strip->proxy->size
+ = 25.0;
+ }
+ seq->strip->proxy->quality =90;
+ }
+ }
+ SEQ_END
}
+
+ sce= sce->id.next;
}
+
}
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
@@ -9526,8 +9517,6 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
expand_doit(fd, mainvar, part->dup_group);
expand_doit(fd, mainvar, part->eff_group);
expand_doit(fd, mainvar, part->bb_ob);
-
- expand_animdata(fd, mainvar, part->adt);
}
static void expand_group(FileData *fd, Main *mainvar, Group *group)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index c433232d084..f8112406e80 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -382,7 +382,6 @@ static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not
/*These functions are used by blender's .blend system for file saving/loading.*/
void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd);
void IDP_WriteProperty(IDProperty *prop, void *wd);
-static void write_animdata(WriteData *wd, AnimData *adt); // XXX code needs reshuffling, but not before NLA SoC is merged back into 2.5
static void IDP_WriteArray(IDProperty *prop, void *wd)
{
@@ -550,25 +549,6 @@ static void write_userdef(WriteData *wd)
}
}
-/* TODO: replace *cache with *cachelist once it's coded */
-#define PTCACHE_WRITE_PSYS 0
-#define PTCACHE_WRITE_CLOTH 1
-static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
-{
- writestruct(wd, DATA, "PointCache", 1, cache);
-
- if((cache->flag & PTCACHE_DISK_CACHE)==0) {
- PTCacheMem *pm = cache->mem_cache.first;
-
- for(; pm; pm=pm->next) {
- writestruct(wd, DATA, "PTCacheMem", 1, pm);
- if(type==PTCACHE_WRITE_PSYS)
- writestruct(wd, DATA, "ParticleKey", pm->totpoint, pm->data);
- else if(type==PTCACHE_WRITE_CLOTH)
- writedata(wd, DATA, 9 * sizeof(float) * pm->totpoint, pm->data);
- }
- }
-}
static void write_particlesettings(WriteData *wd, ListBase *idbase)
{
ParticleSettings *part;
@@ -579,7 +559,6 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
/* write LibData */
writestruct(wd, ID_PA, "ParticleSettings", 1, part);
if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
- if (part->adt) write_animdata(wd, part->adt);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
}
@@ -606,8 +585,8 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
}
if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
writestruct(wd, DATA, "SoftBody", 1, psys->soft);
- if(psys->soft) write_pointcaches(wd, psys->soft->pointcache, PTCACHE_WRITE_PSYS);
- write_pointcaches(wd, psys->pointcache, PTCACHE_WRITE_PSYS);
+ if(psys->soft) writestruct(wd, DATA, "PointCache", 1, psys->soft->pointcache);
+ writestruct(wd, DATA, "PointCache", 1, psys->pointcache);
}
}
@@ -1028,7 +1007,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
- write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
+ writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
}
else if(md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
@@ -1605,6 +1584,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
base= base->next;
}
+ writestruct(wd, DATA, "Radio", 1, sce->radio);
writestruct(wd, DATA, "ToolSettings", 1, sce->toolsettings);
if(sce->toolsettings->vpaint)
writestruct(wd, DATA, "VPaint", 1, sce->toolsettings->vpaint);
diff --git a/source/blender/blenpluginapi/intern/Makefile b/source/blender/blenpluginapi/intern/Makefile
index 20a61e9a25c..51905cad8ec 100644
--- a/source/blender/blenpluginapi/intern/Makefile
+++ b/source/blender/blenpluginapi/intern/Makefile
@@ -33,6 +33,10 @@ DIR = $(OCGDIR)/blender/$(LIBNAME)
include nan_compile.mk
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris"))
+ CFLAGS += -shared
+endif
+
CFLAGS += $(LEVEL_1_C_WARNINGS)
# path to our own external headerfiles. On win2k this needs to be
diff --git a/source/blender/editors/animation/Makefile b/source/blender/editors/animation/Makefile
index a7f36aa58ac..19b62891b63 100644
--- a/source/blender/editors/animation/Makefile
+++ b/source/blender/editors/animation/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
index 05d50f98e8e..c52ade1bba8 100644
--- a/source/blender/editors/animation/anim_channels.c
+++ b/source/blender/editors/animation/anim_channels.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index d0e83eeaec7..cfbd6d2bced 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/armature/BIF_generate.h b/source/blender/editors/armature/BIF_generate.h
index bde079c45fb..2d46cfa41e6 100644
--- a/source/blender/editors/armature/BIF_generate.h
+++ b/source/blender/editors/armature/BIF_generate.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BIF_generate.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
index c39f410424a..56f7e4cdd5d 100644
--- a/source/blender/editors/armature/BIF_retarget.h
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BIF_retarget.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/armature/Makefile b/source/blender/editors/armature/Makefile
index 0291bcb1830..6c7ce81a8a1 100644
--- a/source/blender/editors/armature/Makefile
+++ b/source/blender/editors/armature/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c
index 6d271375c64..a50f767cf14 100644
--- a/source/blender/editors/armature/editarmature_generate.c
+++ b/source/blender/editors/armature/editarmature_generate.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editarmature_generate.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index fb030b91ce1..1b879569e9c 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editarmature_sketch.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -243,7 +243,6 @@ void BIF_makeListTemplates(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
Base *base;
int index = 0;
@@ -264,7 +263,7 @@ void BIF_makeListTemplates(bContext *C)
index++;
BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
- if (ob == ts->skgen_template)
+ if (ob == scene->toolsettings->skgen_template)
{
TEMPLATES_CURRENT = index;
}
@@ -306,9 +305,8 @@ char *BIF_listTemplates(bContext *C)
int BIF_currentTemplate(bContext *C)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL)
+ Scene *scene = CTX_data_scene(C);
+ if (TEMPLATES_CURRENT == 0 && scene->toolsettings->skgen_template != NULL)
{
GHashIterator ghi;
BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
@@ -318,7 +316,7 @@ int BIF_currentTemplate(bContext *C)
Object *ob = BLI_ghashIterator_getValue(&ghi);
int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
- if (ob == ts->skgen_template)
+ if (ob == scene->toolsettings->skgen_template)
{
TEMPLATES_CURRENT = key;
break;
@@ -362,8 +360,8 @@ RigGraph* sk_makeTemplateGraph(bContext *C, Object *ob)
int BIF_nbJointsTemplate(bContext *C)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template);
+ Scene *scene = CTX_data_scene(C);
+ RigGraph *rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
if (rg)
{
@@ -377,7 +375,7 @@ int BIF_nbJointsTemplate(bContext *C)
char * BIF_nameBoneTemplate(bContext *C)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
SK_Sketch *stk = GLOBAL_sketch;
RigGraph *rg;
int index = 0;
@@ -387,7 +385,7 @@ char * BIF_nameBoneTemplate(bContext *C)
index = stk->active_stroke->nb_points;
}
- rg = sk_makeTemplateGraph(C, ts->skgen_template);
+ rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
if (rg == NULL)
{
@@ -420,14 +418,14 @@ void BIF_freeTemplates(bContext *C)
void BIF_setTemplate(bContext *C, int index)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (index > 0)
{
- ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
+ scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
}
else
{
- ts->skgen_template = NULL;
+ scene->toolsettings->skgen_template = NULL;
if (TEMPLATE_RIGG != NULL)
{
@@ -441,19 +439,19 @@ void BIF_setTemplate(bContext *C, int index)
void sk_autoname(bContext *C, ReebArc *arc)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME)
+ Scene *scene = CTX_data_scene(C);
+ if (scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
{
if (arc == NULL)
{
- char *num = ts->skgen_num_string;
+ char *num = scene->toolsettings->skgen_num_string;
int i = atoi(num);
i++;
BLI_snprintf(num, 8, "%i", i);
}
else
{
- char *side = ts->skgen_side_string;
+ char *side = scene->toolsettings->skgen_side_string;
int valid = 0;
int caps = 0;
@@ -527,7 +525,7 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
void sk_retargetStroke(bContext *C, SK_Stroke *stk)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
float imat[4][4];
float tmat[3][3];
@@ -543,7 +541,7 @@ void sk_retargetStroke(bContext *C, SK_Stroke *stk)
sk_autoname(C, arc);
- rg = sk_makeTemplateGraph(C, ts->skgen_template);
+ rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
BIF_retargetArc(C, arc, rg);
@@ -1410,10 +1408,10 @@ void sk_startStroke(SK_Sketch *sketch)
void sk_endStroke(bContext *C, SK_Sketch *sketch)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
sk_shrinkStrokeBuffer(sketch->active_stroke);
- if (ts->bone_sketching & BONE_SKETCHING_ADJUST)
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
{
sk_endOverdraw(sketch);
}
@@ -1523,10 +1521,10 @@ int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_Dra
int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
int point_added = 0;
- if (ts->snap_mode == SCE_SNAP_MODE_VOLUME)
+ if (scene->snap_mode == SCE_SNAP_MODE_VOLUME)
{
ListBase depth_peels;
DepthPeel *p1, *p2;
@@ -1559,7 +1557,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
p1->flag = 1;
/* if peeling objects, take the first and last from each object */
- if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
+ if (scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
{
DepthPeel *peel;
for (peel = p1->next; peel; peel = peel->next)
@@ -1629,7 +1627,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
/* snap to strokes */
- // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
+ // if (scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
{
SK_Point *spt = NULL;
@@ -1715,7 +1713,7 @@ int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_Dra
void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
int point_added = 0;
if (snap)
@@ -1728,7 +1726,7 @@ void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawDa
point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
}
- if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
+ if (stk == sketch->active_stroke && scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
{
sk_updateOverdraw(C, sketch, stk, dd);
}
@@ -1953,7 +1951,7 @@ static int iteratorStopped(void *arg)
void sk_convertStroke(bContext *C, SK_Stroke *stk)
{
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
bArmature *arm = obedit->data;
SK_Point *head;
EditBone *parent = NULL;
@@ -1992,17 +1990,17 @@ void sk_convertStroke(bContext *C, SK_Stroke *stk)
initStrokeIterator(iter, stk, head_index, i);
- if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
{
- bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
}
- else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+ else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
{
- bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
}
- else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+ else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
{
- bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
}
}
@@ -2044,14 +2042,14 @@ void sk_convertStroke(bContext *C, SK_Stroke *stk)
void sk_convert(bContext *C, SK_Sketch *sketch)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
SK_Stroke *stk;
for (stk = sketch->strokes.first; stk; stk = stk->next)
{
if (stk->selected == 1)
{
- if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
{
sk_retargetStroke(C, stk);
}
@@ -2695,7 +2693,7 @@ void sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
rect.ymin= mval[1]-5;
rect.ymax= mval[1]+5;
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
if (hits>0)
{
@@ -2745,7 +2743,6 @@ void sk_queueRedrawSketch(SK_Sketch *sketch)
void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
{
- ToolSettings *ts= scene->toolsettings;
SK_Stroke *stk;
glDisable(GL_DEPTH_TEST);
@@ -2782,7 +2779,7 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
if (stk->selected == 1)
{
- sk_drawStrokeSubdivision(ts, stk);
+ sk_drawStrokeSubdivision(scene->toolsettings, stk);
}
}
@@ -2797,9 +2794,9 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
{
SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
- if (ts->bone_sketching & BONE_SKETCHING_QUICK)
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
{
- sk_drawStrokeSubdivision(ts, sketch->active_stroke);
+ sk_drawStrokeSubdivision(scene->toolsettings, sketch->active_stroke);
}
if (last != NULL)
@@ -2842,7 +2839,7 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (sketch->active_stroke != NULL)
{
@@ -2850,9 +2847,9 @@ int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
sk_endStroke(C, sketch);
- if (ts->bone_sketching & BONE_SKETCHING_QUICK)
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
{
- if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
{
sk_retargetStroke(C, stk);
}
@@ -3199,11 +3196,11 @@ static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
int ED_operator_sketch_mode_active_stroke(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (obedit &&
obedit->type == OB_ARMATURE &&
- ts->bone_sketching & BONE_SKETCHING &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
GLOBAL_sketch != NULL &&
GLOBAL_sketch->active_stroke != NULL)
{
@@ -3218,12 +3215,12 @@ int ED_operator_sketch_mode_active_stroke(bContext *C)
int ED_operator_sketch_mode_gesture(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (obedit &&
obedit->type == OB_ARMATURE &&
- ts->bone_sketching & BONE_SKETCHING &&
- (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+ (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
GLOBAL_sketch != NULL &&
GLOBAL_sketch->active_stroke == NULL)
{
@@ -3238,12 +3235,12 @@ int ED_operator_sketch_mode_gesture(bContext *C)
int ED_operator_sketch_full_mode(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (obedit &&
obedit->type == OB_ARMATURE &&
- ts->bone_sketching & BONE_SKETCHING &&
- (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0)
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+ (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0)
{
return 1;
}
@@ -3256,11 +3253,11 @@ int ED_operator_sketch_full_mode(bContext *C)
int ED_operator_sketch_mode(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (obedit &&
obedit->type == OB_ARMATURE &&
- ts->bone_sketching & BONE_SKETCHING)
+ scene->toolsettings->bone_sketching & BONE_SKETCHING)
{
return 1;
}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index d74c8dbd0e1..4a0ee474f25 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: meshlaplacian.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index 00c0aefaec7..ff921e93909 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: meshlaplacian.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/curve/Makefile b/source/blender/editors/curve/Makefile
index 6449700e50b..6b1f628f231 100644
--- a/source/blender/editors/curve/Makefile
+++ b/source/blender/editors/curve/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 2146855a75e..a73a54323ee 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -49,6 +49,7 @@ void FONT_OT_case_toggle(struct wmOperatorType *ot);
void FONT_OT_case_set(struct wmOperatorType *ot);
void FONT_OT_style_toggle(struct wmOperatorType *ot);
void FONT_OT_style_set(struct wmOperatorType *ot);
+void FONT_OT_material_set(struct wmOperatorType *ot);
void FONT_OT_text_copy(struct wmOperatorType *ot);
void FONT_OT_text_cut(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 66cde772f3e..5292d86d3c9 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -106,6 +106,7 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(FONT_OT_case_set);
WM_operatortype_append(FONT_OT_style_toggle);
WM_operatortype_append(FONT_OT_style_set);
+ WM_operatortype_append(FONT_OT_material_set);
WM_operatortype_append(FONT_OT_text_copy);
WM_operatortype_append(FONT_OT_text_cut);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 5283aacf39e..466908c562c 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -189,7 +189,7 @@ static short swap_selection_bpoint(BPoint *bp)
return select_bpoint(bp, SELECT, 1, VISIBLE);
}
-int isNurbsel(Nurb *nu)
+short isNurbsel(Nurb *nu)
{
BezTriple *bezt;
BPoint *bp;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 9f2bd6f26f9..5389db9e2ee 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -700,6 +700,50 @@ void FONT_OT_style_toggle(wmOperatorType *ot)
RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
}
+/******************* set material operator ********************/
+
+static int set_material_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int i, mat_nr, selstart, selend;
+
+ if(!BKE_font_getselection(obedit, &selstart, &selend))
+ return OPERATOR_CANCELLED;
+
+ if(RNA_property_is_set(op->ptr, "index"))
+ mat_nr= RNA_int_get(op->ptr, "index");
+ else
+ mat_nr= obedit->actcol;
+
+ for(i=selstart; i<=selend; i++)
+ ef->textbufinfo[i].mat_nr = mat_nr;
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_material_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Material";
+ ot->idname= "FONT_OT_material_set";
+
+ /* api callbacks */
+ ot->exec= set_material_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Material Index", "Material slot index.", 0, INT_MAX);
+}
+
/******************* copy text operator ********************/
static void copy_selection(Object *obedit)
diff --git a/source/blender/editors/datafiles/Bfont.c b/source/blender/editors/datafiles/Bfont.c
index cd45debcbe4..4080a0d369f 100644
--- a/source/blender/editors/datafiles/Bfont.c
+++ b/source/blender/editors/datafiles/Bfont.c
@@ -1,6 +1,6 @@
/* DataToC output of file <Bfont> */
/*
- * $Id$
+ * $Id: Bfont.c 125 2002-11-25 12:02:15Z mein $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/datafiles/Makefile b/source/blender/editors/datafiles/Makefile
index d7bb4e7222f..4162125623e 100644
--- a/source/blender/editors/datafiles/Makefile
+++ b/source/blender/editors/datafiles/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/gpencil/Makefile b/source/blender/editors/gpencil/Makefile
index 9bc5f491a83..f4c1cd246f4 100644
--- a/source/blender/editors/gpencil/Makefile
+++ b/source/blender/editors/gpencil/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index c0c1cbc7ac6..bad86c170ab 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index c1b3b056d62..014201648c9 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BIF_gl.h 10455 2007-04-04 13:18:41Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 2cebc6a572a..c619ee80f70 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -30,7 +30,6 @@
struct Base;
struct bContext;
-struct Nurb;
struct Object;
struct Scene;
struct Text;
@@ -53,8 +52,6 @@ void mouse_nurb (struct bContext *C, short mval[2], int extend);
struct Nurb *add_nurbs_primitive(struct bContext *C, int type, int newname);
-int isNurbsel (struct Nurb *nu);;
-
/* editfont.h */
void undo_push_font (struct bContext *C, char *name);
void make_editText (struct Object *obedit);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 5d24b93418b..c1802c2952b 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: ED_datafiles.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/ED_fluidsim.h b/source/blender/editors/include/ED_fluidsim.h
index 586f16f42aa..bda879173c3 100644
--- a/source/blender/editors/include/ED_fluidsim.h
+++ b/source/blender/editors/include/ED_fluidsim.h
@@ -1,7 +1,7 @@
/**
* BKE_fluidsim.h
*
- * $Id$
+ * $Id: LBM_fluidsim.h 17433 2008-11-12 21:16:53Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index e104bce90f6..81420ac95e5 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BDR_drawaction.h 17579 2008-11-26 11:01:56Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 9d063910aa9..fbb469f8d43 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BIF_keyframing.h 17216 2008-10-29 11:20:02Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -178,9 +178,9 @@ void ANIM_OT_remove_driver_button(struct wmOperatorType *ot);
/* Auto-Keying macros for use by various tools */
/* check if auto-keyframing is enabled (per scene takes presidence) */
-#define IS_AUTOKEY_ON(scene) ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
+#define IS_AUTOKEY_ON(scene) ((scene) ? (scene->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
/* check the mode for auto-keyframing (per scene takes presidence) */
-#define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
+#define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
/* check if a flag is set for auto-keyframing (as userprefs only!) */
#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag)
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 937f6384f6a..6dff4ee6ca4 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -147,9 +147,6 @@ int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short r
void EM_hide_mesh(struct EditMesh *em, int swap);
void EM_reveal_mesh(struct EditMesh *em);
-void EM_select_by_material(struct EditMesh *em, int index);
-void EM_deselect_by_material(struct EditMesh *em, int index);
-
/* editface.c */
struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index e4e4b1d0486..bfa819632c9 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -63,7 +63,6 @@ struct Base *ED_object_add_duplicate(struct Scene *scene, struct Base *base, int
#define EM_FREEDATA 1
#define EM_FREEUNDO 2
#define EM_WAITCURSOR 4
-#define EM_DO_UNDO 8
void ED_object_exit_editmode(struct bContext *C, int flag);
void ED_object_enter_editmode(struct bContext *C, int flag);
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 43cb5053f48..0e5d7302837 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: ED_editparticle.h $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/include/ED_previewrender.h b/source/blender/editors/include/ED_previewrender.h
index 10067510e53..c74cb0f9958 100644
--- a/source/blender/editors/include/ED_previewrender.h
+++ b/source/blender/editors/include/ED_previewrender.h
@@ -29,14 +29,17 @@
struct View3D;
struct SpaceButs;
struct RenderInfo;
-struct Scene;
struct Image;
+struct ScrArea;
+struct uiBlock;
struct Render;
struct bContext;
struct ID;
#define PREVIEW_RENDERSIZE 140
+typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
+
/* stores rendered preview - is also used for icons */
typedef struct RenderInfo {
int pr_rectx;
@@ -71,7 +74,6 @@ void ED_preview_init_dbase(void);
void ED_preview_free_dbase(void);
void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, int sizex, int sizey);
-void ED_preview_iconrender(struct Scene *scene, struct ID *id, int *rect, int sizex, int sizey);
void ED_preview_draw(const struct bContext *C, void *idp, rcti *rect);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b576299c1d0..38e52a8f59c 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -132,8 +132,6 @@ int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, in
/* modes */
void ED_view3d_exit_paint_modes(struct bContext *C);
-/* get 3d region from context, also if mouse is in header or toolbar */
-struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C);
#endif /* ED_VIEW3D_H */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 602e94838b7..a38dfd93c30 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -74,8 +74,8 @@ DEF_ICON(ICON_CHECKBOX_DEHLT)
DEF_ICON(ICON_CHECKBOX_HLT)
DEF_ICON(ICON_UNLOCKED)
DEF_ICON(ICON_LOCKED)
-DEF_ICON(ICON_UNPINNED)
DEF_ICON(ICON_PINNED)
+DEF_ICON(ICON_UNPINNED)
DEF_ICON(ICON_BLANK015)
DEF_ICON(ICON_RIGHTARROW)
DEF_ICON(ICON_DOWNARROW_HLT)
@@ -658,12 +658,12 @@ DEF_ICON(ICON_SNAP_VERTEX)
DEF_ICON(ICON_SNAP_EDGE)
DEF_ICON(ICON_SNAP_FACE)
DEF_ICON(ICON_SNAP_VOLUME)
-DEF_ICON(ICON_UVS_FACE)
DEF_ICON(ICON_STICKY_UVS_LOC)
DEF_ICON(ICON_STICKY_UVS_DISABLE)
DEF_ICON(ICON_STICKY_UVS_VERT)
DEF_ICON(ICON_CLIPUV_DEHLT)
DEF_ICON(ICON_CLIPUV_HLT)
+DEF_ICON(ICON_BLANK219)
DEF_ICON(ICON_SNAP_PEEL_OBJECT)
DEF_ICON(ICON_BLANK221)
DEF_ICON(ICON_GRID)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 333536137cc..c53087464c0 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: UI_interface.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -53,8 +53,6 @@ struct uiStyle;
struct uiFontStyle;
struct ColorBand;
struct CurveMapping;
-struct Image;
-struct ImageUser;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -417,7 +415,7 @@ void uiBlockPickerButtons(struct uiBlock *block, float *col, float *hsv, float *
void uiBlockColorbandButtons(struct uiBlock *block, struct ColorBand *coba, struct rctf *butr, int event);
uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2);
-void uiDefAutoButsRNA(const struct bContext *C, uiLayout *layout, struct PointerRNA *ptr, int columns);
+void uiDefAutoButsRNA(const struct bContext *C, uiLayout *layout, struct PointerRNA *ptr);
/* Links
*
@@ -454,9 +452,9 @@ typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, char *str,
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
/* use inside searchfunc to add items */
-int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid);
+int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin);
/* bfunc gets search item *poin as arg2, or if NULL the old string */
-void uiButSetSearchFunc (uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active);
+void uiButSetSearchFunc (uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc);
/* height in pixels, it's using hardcoded values still */
int uiSearchBoxhHeight(void);
@@ -609,15 +607,13 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
- char *newop, char *unlinkop);
+ char *newop, char *openop, char *unlinkop);
uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr);
uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct ID *id);
void uiTemplateColorRamp(uiLayout *layout, struct ColorBand *coba, int expand);
void uiTemplateCurveMapping(uiLayout *layout, struct CurveMapping *cumap, int type);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname);
-void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
-ListBase uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, char *activeprop, int rows, int columns, int compact);
/* items */
void uiItemO(uiLayout *layout, char *name, int icon, char *opname);
@@ -634,7 +630,6 @@ void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, cha
void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int expand, int slider, int toggle);
void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value);
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname);
-void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname);
void uiItemL(uiLayout *layout, char *name, int icon); /* label */
void uiItemM(uiLayout *layout, struct bContext *C, char *name, int icon, char *menuname); /* menu */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 1ae3634c73b..7168e593a8a 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: UI_resources.h 13057 2007-12-30 12:08:28Z aligorith $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/interface/Makefile b/source/blender/editors/interface/Makefile
index a3d0692f1e1..dfc8187de49 100644
--- a/source/blender/editors/interface/Makefile
+++ b/source/blender/editors/interface/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index fcea74cc22b..5ffc6440dc4 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: interface.c 16882 2008-10-02 12:29:45Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -80,6 +80,7 @@
*/
static void ui_free_but(const bContext *C, uiBut *but);
+static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but);
/* ************* translation ************** */
@@ -670,8 +671,7 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
/* widgets */
for(but= block->buttons.first; but; but= but->next) {
ui_but_to_pixelrect(&rect, ar, block, but);
- if(!(but->flag & UI_HIDDEN))
- ui_draw_but(C, ar, &style, but, &rect);
+ ui_draw_but(C, ar, &style, but, &rect);
}
/* restore matrix */
@@ -1281,13 +1281,17 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
else if(type == PROP_POINTER) {
/* RNA pointer */
PointerRNA ptr= RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
- buf= RNA_struct_name_get_alloc(&ptr, str, maxlen);
- }
+ PropertyRNA *nameprop;
- if(!buf) {
- BLI_strncpy(str, "", maxlen);
+ if(ptr.data && (nameprop = RNA_struct_name_property(ptr.type)))
+ buf= RNA_property_string_get_alloc(&ptr, nameprop, str, maxlen);
+ else
+ BLI_strncpy(str, "", maxlen);
}
- else if(buf && buf != str) {
+ else
+ BLI_strncpy(str, "", maxlen);
+
+ if(buf && buf != str) {
/* string was too long, we have to truncate */
BLI_strncpy(str, buf, maxlen);
MEM_freeN(buf);
@@ -1333,6 +1337,72 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
}
}
+static void ui_rna_ID_collection(bContext *C, uiBut *but, PointerRNA *ptr, PropertyRNA **prop)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *iprop;
+ StructRNA *srna;
+
+ /* look for collection property in Main */
+ RNA_pointer_create(NULL, &RNA_Main, CTX_data_main(C), ptr);
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+ *prop= NULL;
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ iprop= iter.ptr.data;
+
+ /* if it's a collection and has same pointer type, we've got it */
+ if(RNA_property_type(iprop) == PROP_COLLECTION) {
+ srna= RNA_property_pointer_type(ptr, iprop);
+
+ if(RNA_property_pointer_type(ptr, but->rnaprop) == srna) {
+ *prop= iprop;
+ break;
+ }
+ }
+ }
+
+ RNA_property_collection_end(&iter);
+}
+
+/* autocomplete callback for RNA pointers */
+static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but)
+{
+ uiBut *but= arg_but;
+ AutoComplete *autocpl;
+ CollectionPropertyIterator iter;
+ PointerRNA ptr;
+ PropertyRNA *prop, *nameprop;
+ char *name;
+
+ if(str[0]==0) return;
+
+ /* get the collection */
+ ui_rna_ID_collection(C, but, &ptr, &prop);
+ if(prop==NULL) return;
+
+ autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
+ RNA_property_collection_begin(&ptr, prop, &iter);
+
+ /* loop over items in collection */
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ name= RNA_property_string_get_alloc(&iter.ptr, nameprop, NULL, 0);
+
+ if(name) {
+ /* test item name */
+ autocomplete_do_name(autocpl, name);
+ MEM_freeN(name);
+ }
+ }
+ }
+
+ RNA_property_collection_end(&iter);
+ autocomplete_end(autocpl, str);
+}
+
int ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
if(but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
@@ -1351,21 +1421,21 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
PointerRNA ptr, rptr;
PropertyRNA *prop;
+ /* XXX only ID pointers at the moment, needs to support
+ * custom collection too for bones, vertex groups, .. */
+ ui_rna_ID_collection(C, but, &ptr, &prop);
+
if(str == NULL || str[0] == '\0') {
- RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
+ memset(&rptr, 0, sizeof(rptr));
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
return 1;
}
- else {
- ptr= but->rnasearchpoin;
- prop= but->rnasearchprop;
-
- if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr))
- RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
-
+ else if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
return 1;
}
-
- return 0;
+ else
+ return 0;
}
}
}
@@ -2077,10 +2147,13 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2);
}
- if((block->flag & UI_BLOCK_LOOP) || ELEM7(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM, SEARCH_MENU))
- but->flag |= (UI_TEXT_LEFT|UI_ICON_LEFT);
- else if(but->type==BUT_TOGDUAL)
+ if((block->flag & UI_BLOCK_LOOP) || ELEM6(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM)) {
+ but->flag |= UI_TEXT_LEFT;
+ }
+
+ if(but->type==BUT_TOGDUAL) {
but->flag |= UI_ICON_LEFT;
+ }
but->flag |= (block->flag & UI_BUT_ALIGN);
@@ -2230,6 +2303,10 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
but->rnaindex= index;
else
but->rnaindex= 0;
+
+ if(type == IDPOIN)
+ uiButSetCompleteFunc(but, ui_rna_ID_autocomplete, but);
+
}
if(icon) {
@@ -2345,11 +2422,7 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name)
else {
/* remove from truncate what is not in bone->name */
for(a=0; a<autocpl->maxlen-1; a++) {
- if(name[a] == 0) {
- truncate[a]= 0;
- break;
- }
- else if(truncate[a]!=name[a])
+ if(truncate[a]!=name[a])
truncate[a]= 0;
}
}
@@ -2680,7 +2753,7 @@ void uiBlockFlipOrder(uiBlock *block)
uiBut *but, *next;
float centy, miny=10000, maxy= -10000;
- if(U.uiflag & USER_MENUFIXEDORDER)
+ if(!(U.uiflag & USER_DIRECTIONALORDER))
return;
for(but= block->buttons.first; but; but= but->next) {
@@ -2919,15 +2992,15 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
}
/* arg is user value, searchfunc and handlefunc both get it as arg */
-/* if active set, button opens with this item visible and selected */
-void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active)
+void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc)
{
but->search_func= sfunc;
but->search_arg= arg;
- uiButSetFunc(but, bfunc, arg, active);
+ uiButSetFunc(but, bfunc, arg, NULL);
}
+
/* Program Init/Exit */
void UI_init(void)
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 8400fee0c55..6d6d4ab9299 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 92c888ac772..fb5afbf5e36 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -112,9 +112,6 @@ typedef struct uiHandleButtonData {
/* tooltip */
ARegion *tooltip;
wmTimer *tooltiptimer;
-
- /* auto open */
- int used_mouse;
wmTimer *autoopentimer;
/* text selection/editing */
@@ -407,15 +404,7 @@ static void ui_apply_but_TOG(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
{
- uiBut *bt;
-
ui_set_but_val(but, but->hardmax);
-
- /* states of other row buttons */
- for(bt= block->buttons.first; bt; bt= bt->next)
- if(bt!=but && bt->poin==but->poin && bt->type==ROW)
- ui_check_but(bt);
-
ui_apply_but_func(C, but);
data->retval= but->retval;
@@ -749,8 +738,11 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
ui_apply_but_ROW(C, block, but, data);
break;
case SCROLL:
+ break;
case NUM:
case NUMABS:
+ ui_apply_but_NUM(C, but, data);
+ break;
case SLI:
case NUMSLI:
ui_apply_but_NUM(C, but, data);
@@ -1226,14 +1218,8 @@ static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData
int changed= 1;
str= data->str;
-
- if(data->searchbox)
- ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
- else
- but->autocomplete_func(C, str, but->autofunc_arg);
-
+ but->autocomplete_func(C, str, but->autofunc_arg);
but->pos= strlen(str);
- but->selsta= but->selend= but->pos;
return changed;
}
@@ -1360,14 +1346,14 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
return;
for(but= actbut->next; but; but= but->next) {
- if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
data->postbut= but;
data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
return;
}
}
for(but= block->buttons.first; but!=actbut; but= but->next) {
- if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
data->postbut= but;
data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
return;
@@ -1384,14 +1370,14 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
return;
for(but= actbut->prev; but; but= but->prev) {
- if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
data->postbut= but;
data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
return;
}
}
for(but= block->buttons.last; but!=actbut; but= but->prev) {
- if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
data->postbut= but;
data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
return;
@@ -1447,6 +1433,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
}
else if(inbox) {
+ printf("release inside \n");
button_activate_state(C, but, BUTTON_STATE_EXIT);
retval= WM_UI_HANDLER_BREAK;
}
@@ -1515,7 +1502,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case TABKEY:
/* there is a key conflict here, we can't tab with autocomplete */
- if(but->autocomplete_func || data->searchbox) {
+ if(but->autocomplete_func) {
changed= ui_textedit_autocomplete(C, but, data);
retval= WM_UI_HANDLER_BREAK;
}
@@ -2066,11 +2053,6 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, i
if(but->type==NUMSLI) deler= ((but->x2-but->x1) - 5.0*but->aspect);
else if(but->type==HSVSLI) deler= ((but->x2-but->x1)/2 - 5.0*but->aspect);
- else if(but->type==SCROLL) {
- int horizontal= (but->x2 - but->x1 > but->y2 - but->y1);
- float size= (horizontal)? (but->x2-but->x1): -(but->y2-but->y1);
- deler= size*(but->softmax - but->softmin)/(but->softmax - but->softmin + but->a1);
- }
else deler= (but->x2-but->x1- 5.0*but->aspect);
f= (float)(mx-data->dragstartx)/deler + data->dragfstart;
@@ -2241,54 +2223,6 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
-{
- int mx, my, click= 0;
- int retval= WM_UI_HANDLER_CONTINUE;
- int horizontal= (but->x2 - but->x1 > but->y2 - but->y1);
-
- mx= event->x;
- my= event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if(data->state == BUTTON_STATE_HIGHLIGHT) {
- if(event->val==KM_PRESS) {
- if(event->type == LEFTMOUSE) {
- if(horizontal) {
- data->dragstartx= mx;
- data->draglastx= mx;
- }
- else {
- data->dragstartx= my;
- data->draglastx= my;
- }
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- retval= WM_UI_HANDLER_BREAK;
- }
- else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
- click= 1;
- }
- }
- else if(data->state == BUTTON_STATE_NUM_EDITING) {
- if(event->type == ESCKEY) {
- data->cancel= 1;
- data->escapecancel= 1;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if(event->type == MOUSEMOVE) {
- if(ui_numedit_but_SLI(but, data, 0, 0, (horizontal)? mx: my))
- ui_numedit_apply(C, block, but, data);
- }
-
- retval= WM_UI_HANDLER_BREAK;
- }
-
- return retval;
-}
-
static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
{
@@ -3131,9 +3065,13 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
case OPTIONN:
retval= ui_do_but_TOG(C, but, data, event);
break;
+#if 0
case SCROLL:
- retval= ui_do_but_SCROLL(C, block, but, data, event);
+ /* DrawBut(b, 1); */
+ /* do_scrollbut(b); */
+ /* DrawBut(b,0); */
break;
+#endif
case NUM:
case NUMABS:
retval= ui_do_but_NUM(C, block, but, data, event);
@@ -3294,8 +3232,7 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
for(but=block->buttons.first; but; but= but->next) {
if(ELEM3(but->type, LABEL, ROUNDBOX, SEPR))
continue;
- if(but->flag & UI_HIDDEN)
- continue;
+
if(ui_but_contains_pt(but, mx, my))
/* give precedence to already activated buttons */
if(!butover || (!butover->active && but->active))
@@ -3347,7 +3284,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* automatic open pulldown block timer */
if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) {
- if(data->used_mouse && !data->autoopentimer) {
+ if(!data->autoopentimer) {
int time;
if(but->block->auto_open==2) time= 1; // test for toolbox
@@ -3450,9 +3387,6 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
if(but->block->auto_open_last+BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer())
but->block->auto_open= 0;
- if(type == BUTTON_ACTIVATE_OVER) {
- data->used_mouse= 1;
- }
button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
if(type == BUTTON_ACTIVATE_OPEN) {
@@ -3771,19 +3705,12 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
button_activate_exit(C, data, but, 1);
}
else if(menu->menuretval == UI_RETURN_OUT) {
- if(event->type==MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) {
+ if(ui_mouse_inside_button(data->region, but, event->x, event->y)) {
button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
}
else {
- but= ui_but_find_activated(data->region);
- if(but) {
- but->active->used_mouse= 0;
- button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
- }
- else {
- data->cancel= 1;
- button_activate_exit(C, data, but, 1);
- }
+ data->cancel= 1;
+ button_activate_exit(C, data, but, 1);
}
}
}
@@ -4122,7 +4049,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
uiBlock *block;
uiHandleButtonData *data;
uiPopupBlockHandle *submenu;
- int mx, my, update;
+ int mx, my;
ar= menu->region;
block= ar->uiblocks.first;
@@ -4140,16 +4067,14 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
menu->butretval= data->retval;
}
}
-
- update= (submenu->menuretval == UI_RETURN_UPDATE);
- if(update)
+ else if(submenu->menuretval == UI_RETURN_UPDATE)
menu->menuretval = UI_RETURN_UPDATE;
/* now let activated button in this menu exit, which
* will actually close the submenu too */
ui_handle_button_return_submenu(C, event, but);
- if(update)
+ if(submenu->menuretval == UI_RETURN_UPDATE)
submenu->menuretval = 0;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 315b8693905..df069069a33 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -41,30 +41,28 @@
#include "BLI_blenlib.h"
#include "BLI_storage_types.h"
-#include "DNA_material_types.h"
#include "DNA_screen_types.h"
-#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+
+#include "BKE_utildefines.h"
#include "BKE_image.h"
#include "BKE_icons.h"
-#include "BKE_utildefines.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
-
-#include "ED_datafiles.h"
-#include "ED_previewrender.h"
-
#include "UI_interface.h"
#include "UI_interface_icons.h"
-#include "UI_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
-#include "interface_intern.h"
+// XXX #include "BIF_previewrender.h"
+// XXX #include "BIF_screen.h"
+#include "UI_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
+#include "interface_intern.h"
+#include "ED_datafiles.h"
#define ICON_IMAGE_W 600
#define ICON_IMAGE_H 640
@@ -652,6 +650,7 @@ void UI_icons_init(int first_dyn_id)
init_internal_icons();
}
+#if 0
static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
{
struct ImBuf *ima;
@@ -728,28 +727,21 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel)
}
/* create single icon from jpg, png etc. */
-static void icon_from_image(Scene *scene, Image *img, int miplevel)
+static void icon_from_image(Image *img, int miplevel)
{
- ImBuf *ibuf= NULL;
- ImageUser iuser;
- PreviewImage *pi;
unsigned int pr_size;
short image_loaded = 0;
+ struct ImBuf* ibuf=NULL;
+ PreviewImage* pi;
/* img->ok is zero when Image cannot load */
if (img==NULL || img->ok==0)
return;
- /* setup dummy image user */
- memset(&iuser, 0, sizeof(ImageUser));
- iuser.ok= iuser.framenr= 1;
- iuser.scene= scene;
-
/* elubie: this needs to be changed: here image is always loaded if not
already there. Very expensive for large images. Need to find a way to
only get existing ibuf */
-
- ibuf = BKE_image_get_ibuf(img, &iuser);
+ ibuf = BKE_image_get_ibuf(img, NULL);
if(ibuf==NULL || ibuf->rect==NULL) {
return;
}
@@ -779,14 +771,18 @@ static void set_alpha(char* cp, int sizex, int sizey, char alpha)
}
}
}
+#endif
/* only called when icon has changed */
/* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int miplevel)
+static void icon_set_image(ID *id, DrawInfo *di, PreviewImage* prv_img, int miplevel)
{
+#if 0 // XXX - preview renders have to be redesigned - possibly low level op (elubie)
RenderInfo ri;
unsigned int pr_size = 0;
+ if (!di) return;
+
if (!prv_img) {
printf("No preview image for this ID: %s\n", id->name);
return;
@@ -795,19 +791,20 @@ static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int mipl
/* no drawing (see last parameter doDraw, just calculate preview image
- hopefully small enough to be fast */
if (GS(id->name) == ID_IM)
- icon_from_image(scene, (struct Image*)id, miplevel);
+ icon_from_image((struct Image*)id, miplevel);
else {
/* create the preview rect */
icon_create_mipmap(prv_img, miplevel);
ri.curtile= 0;
ri.tottile= 0;
+ ri.rect = NULL;
ri.pr_rectx = prv_img->w[miplevel];
ri.pr_recty = prv_img->h[miplevel];
+
pr_size = ri.pr_rectx*ri.pr_recty*sizeof(unsigned int);
- ri.rect = MEM_callocN(pr_size, "pr icon rect");
- ED_preview_iconrender(scene, id, ri.rect, ri.pr_rectx, ri.pr_recty);
+ BIF_previewrender(id, &ri, NULL, PR_ICON_RENDER);
/* world is rendered with alpha=0, so it wasn't displayed
this could be render option for sky to, for later */
@@ -821,11 +818,15 @@ static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int mipl
}
}
- memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
+ if (ri.rect) {
+ memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
- /* and clean up */
- MEM_freeN(ri.rect);
+ /* and clean up */
+ MEM_freeN(ri.rect);
+ ri.rect = 0;
+ }
}
+#endif
}
static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, int rh, unsigned int *rect)
@@ -911,7 +912,14 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl
PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj);
if (pi) {
- /* no create icon on this level in code */
+ if (!nocreate && (pi->changed[miplevel] ||!pi->rect[miplevel])) /* changed only ever set by dynamic icons */
+ {
+ // XXX waitcursor(1);
+ /* create the preview rect if necessary */
+ icon_set_image((ID*)icon->obj, icon->drawinfo, pi, miplevel);
+ pi->changed[miplevel] = 0;
+ // XXX waitcursor(0);
+ }
if (!pi->rect[miplevel]) return; /* something has gone wrong! */
@@ -920,43 +928,6 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl
}
}
-void ui_id_icon_render(Scene *scene, ID *id)
-{
- PreviewImage *pi = BKE_previewimg_get(id);
-
- if (pi) {
- if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */
- {
- /* create the preview rect if necessary */
- icon_set_image(scene, id, pi, 0);
- pi->changed[0] = 0;
- }
- }
-}
-
-int ui_id_icon_get(Scene *scene, ID *id)
-{
- int iconid= 0;
-
- /* icon */
- switch(GS(id->name))
- {
- case ID_MA: /* fall through */
- case ID_TE: /* fall through */
- case ID_IM: /* fall through */
- case ID_WO: /* fall through */
- case ID_LA: /* fall through */
- iconid= BKE_icon_getid(id);
- /* checks if not exists, or changed */
- ui_id_icon_render(scene, id);
- break;
- default:
- break;
- }
-
- return iconid;
-}
-
static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, int miplevel, int nocreate)
{
int draw_size = preview_size(miplevel);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 1b16155c7e6..3aed2a7c299 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: interface.h 14444 2008-04-16 22:40:48Z hos $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -44,17 +44,12 @@ struct uiStyle;
struct uiWidgetColors;
struct uiLayout;
struct bContextStore;
-struct Scene;
-struct ID;
/* ****************** general defines ************** */
/* visual types for drawing */
/* for time being separated from functional types */
typedef enum {
- /* default */
- UI_WTYPE_REGULAR,
-
/* standard set */
UI_WTYPE_LABEL,
UI_WTYPE_TOGGLE,
@@ -83,8 +78,7 @@ typedef enum {
UI_WTYPE_SWATCH,
UI_WTYPE_RGB_PICKER,
UI_WTYPE_NORMAL,
- UI_WTYPE_BOX,
- UI_WTYPE_SCROLL
+ UI_WTYPE_BOX
} uiWidgetTypeEnum;
@@ -104,7 +98,7 @@ typedef enum {
#define UI_ACTIVE 4
#define UI_HAS_ICON 8
#define UI_TEXTINPUT 16
-#define UI_HIDDEN 32
+
/* warn: rest of uiBut->flag in UI_interface.h */
/* internal panel drawing defines */
@@ -211,9 +205,6 @@ struct uiBut {
struct PropertyRNA *rnaprop;
int rnaindex;
- struct PointerRNA rnasearchpoin;
- struct PropertyRNA *rnasearchprop;
-
/* Operator data */
struct wmOperatorType *optype;
int opcontext;
@@ -374,7 +365,6 @@ void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
int ui_searchbox_inside(struct ARegion *ar, int x, int y);
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset);
-void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, struct wmEvent *event);
void ui_searchbox_apply(uiBut *but, struct ARegion *ar);
void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
@@ -426,15 +416,11 @@ extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *s
struct ThemeUI;
void ui_widget_color_init(struct ThemeUI *tui);
-void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state);
+void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int state);
/* interface_style.c */
void uiStyleInit(void);
-/* interface_icons.c */
-void ui_id_icon_render(struct Scene *scene, struct ID *id);
-int ui_id_icon_get(struct Scene *scene, struct ID *id);
-
/* resources.c */
void init_userdef_do_versions(void);
void ui_theme_init_userdef(void);
@@ -442,9 +428,8 @@ void ui_resources_init(void);
void ui_resources_free(void);
/* interface_layout.c */
-void ui_layout_add_but(uiLayout *layout, uiBut *but);
+void ui_layout_add_but(struct uiLayout *layout, uiBut *but);
int ui_but_can_align(uiBut *but);
-void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop);
/* interface_anim.c */
void ui_but_anim_flag(uiBut *but, float cfra);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index f9816235b88..9101fd743ee 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: interface_layout.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -455,10 +455,9 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr,
}
/* create label + button for RNA property */
-static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
+static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
{
uiLayout *sub;
- uiBut *but;
PropertySubType subtype;
sub= uiLayoutRow(layout, 0);
@@ -474,13 +473,12 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, i
if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
- but= uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
+ uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
}
else
- but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
+ uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
uiBlockSetCurLayout(block, layout);
- return but;
}
/********************* Button Items *************************/
@@ -603,7 +601,7 @@ void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
RNA_property_enum_items(&ptr, prop, &item, &totitem);
for(i=0; i<totitem; i++)
- uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
+ uiItemEnumO(layout, NULL, 0, opname, propname, item[i].value);
}
}
@@ -718,8 +716,6 @@ static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA
else if(ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
if(type == PROP_BOOLEAN && strcmp(name, "") != 0)
w += UI_UNIT_X;
- else if(type == PROP_ENUM)
- w += UI_UNIT_X/2;
}
*r_w= w;
@@ -749,11 +745,9 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
if(!icon)
icon= RNA_property_ui_icon(prop);
- if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER))
- name= ui_item_name_add_colon(name, namestr);
- else if(type == PROP_BOOLEAN && len)
+ if(ELEM5(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_ENUM, PROP_POINTER))
name= ui_item_name_add_colon(name, namestr);
- else if(type == PROP_ENUM && index != RNA_ENUM_VALUE)
+ if(type == PROP_BOOLEAN && len)
name= ui_item_name_add_colon(name, namestr);
if(layout->root->type == UI_LAYOUT_MENU) {
@@ -784,10 +778,8 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
else if(type == PROP_ENUM && expand)
ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
/* property with separate label */
- else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
- but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
- ui_but_add_search(but, ptr, prop, NULL, NULL);
- }
+ else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
+ ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
/* single button */
else {
but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
@@ -858,142 +850,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
}
}
-/* Pointer RNA button with search */
-
-static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
-{
- Scene *scene= CTX_data_scene(C);
- uiBut *but= arg_but;
- char *name;
- int i, iconid;
-
- i = 0;
- RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
- iconid= 0;
- if(RNA_struct_is_ID(itemptr.type))
- iconid= ui_id_icon_get(scene, itemptr.data);
-
- name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
-
- if(name) {
- if(BLI_strcasestr(name, str)) {
- if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
- MEM_freeN(name);
- break;
- }
- }
-
- MEM_freeN(name);
- }
-
- i++;
- }
- RNA_PROP_END;
-}
-
-static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
-{
- StructRNA *srna;
-
- /* look for collection property in Main */
- RNA_main_pointer_create(G.main, ptr);
-
- *prop= NULL;
-
- RNA_STRUCT_BEGIN(ptr, iprop) {
- /* if it's a collection and has same pointer type, we've got it */
- if(RNA_property_type(iprop) == PROP_COLLECTION) {
- srna= RNA_property_pointer_type(ptr, iprop);
-
- if(ptype == srna) {
- *prop= iprop;
- break;
- }
- }
- }
- RNA_STRUCT_END;
-}
-
-void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
-{
- StructRNA *ptype;
- PointerRNA sptr;
-
- /* for ID's we do automatic lookup */
- if(!searchprop) {
- if(RNA_property_type(prop) == PROP_POINTER) {
- ptype= RNA_property_pointer_type(ptr, prop);
- search_id_collection(ptype, &sptr, &searchprop);
- searchptr= &sptr;
- }
- }
-
- /* turn button into search button */
- if(searchprop) {
- but->type= SEARCH_MENU;
- but->hardmax= MAX2(but->hardmax, 256);
- but->rnasearchpoin= *searchptr;
- but->rnasearchprop= searchprop;
- but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
-
- uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
- }
-}
-
-void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
-{
- PropertyRNA *prop, *searchprop;
- PropertyType type;
- uiBut *but;
- uiBlock *block;
- StructRNA *icontype;
- int w, h;
-
- /* validate arguments */
- if(!ptr->data || !searchptr->data)
- return;
-
- prop= RNA_struct_find_property(ptr, propname);
-
- if(!prop) {
- printf("uiItemPointerR: property not found: %s\n", propname);
- return;
- }
-
- type= RNA_property_type(prop);
- if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
- printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
- return;
- }
-
- searchprop= RNA_struct_find_property(searchptr, searchpropname);
-
- if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
- printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
- return;
- }
-
- /* get icon & name */
- if(!icon) {
- if(type == PROP_POINTER)
- icontype= RNA_property_pointer_type(ptr, prop);
- else
- icontype= RNA_property_pointer_type(searchptr, searchprop);
-
- icon= RNA_struct_ui_icon(icontype);
- }
- if(!name)
- name= (char*)RNA_property_ui_name(prop);
-
- /* create button */
- block= uiLayoutGetBlock(layout);
-
- ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
- but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
-
- ui_but_add_search(but, ptr, prop, searchptr, searchprop);
-}
-
/* menu item */
static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
@@ -1411,6 +1267,7 @@ static void ui_litem_layout_box(uiLayout *litem)
h= litem->h;
litem->x += style->boxspace;
+ litem->y -= style->boxspace;
if(w != 0) litem->w -= 2*style->boxspace;
if(h != 0) litem->h -= 2*style->boxspace;
@@ -1491,7 +1348,6 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
}
}
- litem->w= x;
litem->h= litem->y - miny;
}
@@ -1597,9 +1453,9 @@ static void ui_litem_layout_free(uiLayout *litem)
totw -= minx;
toth -= miny;
- if(litem->w && totw > 0)
+ if(litem->w && totw > litem->w)
scalex= (float)litem->w/(float)totw;
- if(litem->h && toth > 0)
+ if(litem->h && toth > litem->h)
scaley= (float)litem->h/(float)toth;
x= litem->x;
@@ -1610,15 +1466,15 @@ static void ui_litem_layout_free(uiLayout *litem)
ui_item_size(item, &itemw, &itemh);
if(scalex != 1.0f) {
- newx= (itemx - minx)*scalex;
- itemw= (itemx - minx + itemw)*scalex - newx;
- itemx= minx + newx;
+ newx= itemx*scalex;
+ itemw= (itemx + itemw)*scalex - newx;
+ itemx= newx;
}
if(scaley != 1.0f) {
- newy= (itemy - miny)*scaley;
- itemh= (itemy - miny + itemh)*scaley - newy;
- itemy= miny + newy;
+ newy= itemy*scaley;
+ itemh= (itemy + itemh)*scaley - newy;
+ itemy= newy;
}
ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index eaf78ae89ef..72076175ad5 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -104,7 +104,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
SpaceButs *sbuts= sa->spacedata.first;
return sbuts->align;
}
- else if(ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS))
+ else if(ar->regiontype==RGN_TYPE_UI)
return BUT_VERTICAL;
return 0;
@@ -1288,7 +1288,6 @@ int ui_handler_panel_region(bContext *C, wmEvent *event)
/**************** window level modal panel interaction **************/
-/* note, this is modal handler and should not swallow events for animation */
static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
{
Panel *panel= userdata;
@@ -1304,6 +1303,8 @@ static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
else
panel_activate_state(C, panel, PANEL_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
}
else if(event->type == MOUSEMOVE) {
if(data->state == PANEL_STATE_WAIT_UNTAB)
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 49e3abf4d0c..32bcae77e6b 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -40,7 +40,6 @@
#include "BLI_dynstr.h"
#include "BKE_context.h"
-#include "BKE_icons.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_texture.h"
@@ -182,7 +181,7 @@ MenuData *decompose_menu_string(char *str)
*s= '\0';
s++;
}
- } else if (c=='|' || c == '\n' || c=='\0') {
+ } else if (c=='|' || c=='\0') {
if (nitem) {
*s= '\0';
@@ -434,10 +433,7 @@ struct uiSearchItems {
char **names;
void **pointers;
- int *icons;
-
- AutoComplete *autocpl;
- void *active;
+
};
typedef struct uiSearchboxData {
@@ -452,21 +448,8 @@ typedef struct uiSearchboxData {
/* exported for use by search callbacks */
/* returns zero if nothing to add */
-int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid)
+int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin)
{
- /* hijack for autocomplete */
- if(items->autocpl) {
- autocomplete_do_name(items->autocpl, name);
- return 1;
- }
-
- /* hijack for finding active item */
- if(items->active) {
- if(poin==items->active)
- items->offset_i= items->totitem;
- items->totitem++;
- return 1;
- }
if(items->totitem>=items->maxitem) {
items->more= 1;
@@ -481,7 +464,6 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon
BLI_strncpy(items->names[items->totitem], name, items->maxstrlen);
items->pointers[items->totitem]= poin;
- items->icons[items->totitem]= iconid;
items->totitem++;
@@ -606,52 +588,20 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset)
/* reset vars */
data->items.totitem= 0;
data->items.more= 0;
- if(reset==0) {
+ if(reset==0)
data->items.offset_i= data->items.offset;
- }
else {
data->items.offset_i= data->items.offset= 0;
data->active= 0;
-
- /* handle active */
- if(but->search_func && but->func_arg2) {
- data->items.active= but->func_arg2;
- but->search_func(C, but->search_arg, but->editstr, &data->items);
- data->items.active= NULL;
-
- /* found active item, calculate real offset by centering it */
- if(data->items.totitem) {
- /* first case, begin of list */
- if(data->items.offset_i < data->items.maxitem) {
- data->active= data->items.offset_i+1;
- data->items.offset_i= 0;
- }
- else {
- /* second case, end of list */
- if(data->items.totitem - data->items.offset_i <= data->items.maxitem) {
- data->active= 1 + data->items.offset_i - data->items.totitem + data->items.maxitem;
- data->items.offset_i= data->items.totitem - data->items.maxitem;
- }
- else {
- /* center active item */
- data->items.offset_i -= data->items.maxitem/2;
- data->active= 1 + data->items.maxitem/2;
- }
- }
- }
- data->items.offset= data->items.offset_i;
- data->items.totitem= 0;
- }
}
/* callback */
if(but->search_func)
but->search_func(C, but->search_arg, but->editstr, &data->items);
- /* handle case where editstr is equal to one of items */
- if(reset && data->active==0) {
+ if(reset) {
int a;
-
+ /* handle case where editstr is equal to one of items */
for(a=0; a<data->items.totitem; a++) {
char *cpoin= strchr(data->items.names[a], '|');
@@ -670,18 +620,6 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset)
ED_region_tag_redraw(ar);
}
-void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
-{
- uiSearchboxData *data= ar->regiondata;
-
- data->items.autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
-
- but->search_func(C, but->search_arg, but->editstr, &data->items);
-
- autocomplete_end(data->items.autocpl, str);
- data->items.autocpl= NULL;
-}
-
static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
{
uiSearchboxData *data= ar->regiondata;
@@ -701,21 +639,18 @@ static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
for(a=0; a<data->items.totitem; a++) {
ui_searchbox_butrect(&rect, data, a);
- /* widget itself */
- ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0);
+ ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], (a+1)==data->active?UI_ACTIVE:0);
}
/* indicate more */
if(data->items.more) {
- ui_searchbox_butrect(&rect, data, data->items.maxitem-1);
glEnable(GL_BLEND);
- UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN);
+ UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, 8, ICON_TRIA_DOWN);
glDisable(GL_BLEND);
}
if(data->items.offset) {
- ui_searchbox_butrect(&rect, data, 0);
glEnable(GL_BLEND);
- UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP);
+ UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, data->bbox.ymax-13, ICON_TRIA_UP);
glDisable(GL_BLEND);
}
}
@@ -731,7 +666,6 @@ static void ui_searchbox_region_free(ARegion *ar)
MEM_freeN(data->items.names[a]);
MEM_freeN(data->items.names);
MEM_freeN(data->items.pointers);
- MEM_freeN(data->items.icons);
MEM_freeN(data);
ar->regiondata= NULL;
@@ -745,7 +679,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
uiSearchboxData *data;
float aspect= but->block->aspect;
float x1f, x2f, y1f, y2f;
- int x1, x2, y1, y2, winx, winy, ofsx, ofsy;
+ int x1, x2, y1, y2, winx, winy;
/* create area region */
ar= ui_add_temporary_region(CTX_wm_screen(C));
@@ -798,14 +732,6 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
x2f= but->x2 + 5; /* symmetrical */
y2f= but->y1;
y1f= y2f - uiSearchBoxhHeight();
-
- ofsx= (but->block->panel)? but->block->panel->ofsx: 0;
- ofsy= (but->block->panel)? but->block->panel->ofsy: 0;
-
- x1f += ofsx;
- x2f += ofsx;
- y1f += ofsy;
- y2f += ofsy;
/* minimal width */
if(x2f - x1f < 150) x2f= x1f+150; // XXX arbitrary
@@ -868,7 +794,6 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
data->items.totitem= 0;
data->items.names= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search names");
data->items.pointers= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search pointers");
- data->items.icons= MEM_callocN(SEARCH_ITEMS*sizeof(int), "search icons");
for(x1=0; x1<SEARCH_ITEMS; x1++)
data->items.names[x1]= MEM_callocN(but->hardmax+1, "search pointers");
@@ -1795,118 +1720,24 @@ static void do_picker_small_cb(bContext *C, void *bt1, void *hsv1)
popup->menuretval= UI_RETURN_UPDATE;
}
-/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
-#define SPICK1 150.0
-#define DPICK1 6.0
-/* only the color, a HS circle and V slider */
-static void uiBlockPickerSmall(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
+/* only the color, a circle, slider */
+void uiBlockPickerSmall(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
{
uiBut *bt;
VECCOPY(old, col); // old color stored there, for palette_cb to work
/* HS circle */
- bt= uiDefButF(block, HSVCIRCLE, retval, "", 0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, "");
+ bt= uiDefButF(block, HSVCIRCLE, retval, "", 0, 0,SPICK,SPICK, col, 0.0, 0.0, 0, 0, "");
uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
/* value */
- bt= uiDefButF(block, HSVCUBE, retval, "", SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, "");
- uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
-}
-
-
-static void picker_new_hide_reveal(uiBlock *block, short colormode)
-{
- uiBut *bt;
-
- /* tag buttons */
- for(bt= block->buttons.first; bt; bt= bt->next) {
-
- if(bt->type==NUMSLI || bt->type==TEX) {
- if( bt->str[1]=='e') {
- if(colormode==2) bt->flag &= ~UI_HIDDEN;
- else bt->flag |= UI_HIDDEN;
- }
- else if( ELEM3(bt->str[0], 'R', 'G', 'B')) {
- if(colormode==0) bt->flag &= ~UI_HIDDEN;
- else bt->flag |= UI_HIDDEN;
- }
- else if( ELEM3(bt->str[0], 'H', 'S', 'V')) {
- if(colormode==1) bt->flag &= ~UI_HIDDEN;
- else bt->flag |= UI_HIDDEN;
- }
- }
- }
-}
-
-static void do_picker_new_mode_cb(bContext *C, void *bt1, void *colv)
-{
- uiBut *bt= bt1;
- short colormode= ui_get_but_val(bt);
-
- picker_new_hide_reveal(bt->block, colormode);
-}
-
-
-/* a HS circle, V slider, rgb/hsv/hex sliders */
-static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
-{
- static short colormode= 0; /* temp? 0=rgb, 1=hsv, 2=hex */
- uiBut *bt;
- int width;
-
- VECCOPY(old, col); // old color stored there, for palette_cb to work
-
- /* HS circle */
- bt= uiDefButF(block, HSVCIRCLE, retval, "", 0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
-
- /* value */
- bt= uiDefButF(block, HSVCUBE, retval, "", SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, "");
+ bt= uiDefButF(block, HSVCUBE, retval, "", SPICK+DPICK,0,14,SPICK, col, 0.0, 0.0, 4, 0, "");
uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
-
- /* mode */
- width= (SPICK1+DPICK1+14)/3;
- uiBlockBeginAlign(block);
- bt= uiDefButS(block, ROW, retval, "RGB", 0, -30, width, 19, &colormode, 0.0, 0.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, col);
- bt= uiDefButS(block, ROW, retval, "HSV", width, -30, width, 19, &colormode, 0.0, 1.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, hsv);
- bt= uiDefButS(block, ROW, retval, "Hex", 2*width, -30, width, 19, &colormode, 0.0, 2.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, hexcol);
- uiBlockEndAlign(block);
-
- /* sliders or hex */
- width= (SPICK1+DPICK1+14);
- rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2);
- sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0));
- uiBlockBeginAlign(block);
- bt= uiDefButF(block, NUMSLI, 0, "R ", 0, -60, width, 19, col, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette1_cb, bt, hsv);
- bt= uiDefButF(block, NUMSLI, 0, "G ", 0, -80, width, 19, col+1, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette1_cb, bt, hsv);
- bt= uiDefButF(block, NUMSLI, 0, "B ", 0, -100, width, 19, col+2, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette1_cb, bt, hsv);
- uiBlockEndAlign(block);
-
- uiBlockBeginAlign(block);
- bt= uiDefButF(block, NUMSLI, 0, "H ", 0, -60, width, 19, hsv, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette2_cb, bt, col);
- bt= uiDefButF(block, NUMSLI, 0, "S ", 0, -80, width, 19, hsv+1, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette2_cb, bt, col);
- bt= uiDefButF(block, NUMSLI, 0, "V ", 0, -100, width, 19, hsv+2, 0.0, 1.0, 10, 3, "");
- uiButSetFunc(bt, do_palette2_cb, bt, col);
- uiBlockEndAlign(block);
-
- bt= uiDefBut(block, TEX, 0, "Hex: ", 0, -80, width, 19, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)");
- uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol);
-
- picker_new_hide_reveal(block, colormode);
}
-
static int ui_picker_small_wheel(const bContext *C, uiBlock *block, wmEvent *event)
{
float add= 0.0f;
@@ -1959,22 +1790,13 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu
block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN;
uiBoundsBlock(block, 3);
}
- else if(win->eventstate->alt) {
+ else {
uiBlockPickerSmall(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0);
block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_OUT_1;
uiBoundsBlock(block, 10);
block->block_event_func= ui_picker_small_wheel;
- }
- else {
- uiBlockPickerNew(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0);
- block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN;
- uiBoundsBlock(block, 10);
-
- block->block_event_func= ui_picker_small_wheel;
- }
-
-
+ }
/* and lets go */
block->direction= UI_TOP;
@@ -2642,6 +2464,7 @@ static uiPopupBlockHandle *ui_pup_menu(bContext *C, int maxrow, uiMenuHandleFunc
return menu;
}
+
static void operator_name_cb(bContext *C, void *arg, int retval)
{
const char *opname= arg;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index e8fba38f793..831a8a5bf6c 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -92,7 +92,6 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
style->paneltitle.uifont_id= UIFONT_DEFAULT;
style->paneltitle.points= 13;
style->paneltitle.kerning= 0.0;
- style->paneltitle.overlap= 0;
style->paneltitle.shadow= 5;
style->paneltitle.shadx= 2;
style->paneltitle.shady= -2;
@@ -102,7 +101,6 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
style->grouplabel.uifont_id= UIFONT_DEFAULT;
style->grouplabel.points= 12;
style->grouplabel.kerning= 0.0;
- style->grouplabel.overlap= 0;
style->grouplabel.shadow= 3;
style->grouplabel.shadx= 1;
style->grouplabel.shady= -1;
@@ -111,7 +109,6 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
style->widgetlabel.uifont_id= UIFONT_DEFAULT;
style->widgetlabel.points= 11;
style->widgetlabel.kerning= 0.0;
- style->widgetlabel.overlap= 0;
style->widgetlabel.shadow= 3;
style->widgetlabel.shadx= 1;
style->widgetlabel.shady= -1;
@@ -148,6 +145,22 @@ static uiFont *uifont_to_blfont(int id)
/* *************** draw ************************ */
+static void ui_font_shadow_draw(uiFontStyle *fs, int x, int y, char *str)
+{
+ float color[4];
+
+ glGetFloatv(GL_CURRENT_COLOR, color);
+
+ glColor4f(fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
+
+ BLF_blur(fs->shadow);
+ BLF_position(x+fs->shadx, y+fs->shady, 0.0f);
+ BLF_draw(str);
+ BLF_blur(0);
+
+ glColor4fv(color);
+}
+
void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
{
float height;
@@ -166,23 +179,14 @@ void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
/* clip is very strict, so we give it some space */
BLF_clipping(rect->xmin-1, rect->ymin-4, rect->xmax+1, rect->ymax+4);
BLF_enable(BLF_CLIPPING);
+
+ if(fs->shadow)
+ ui_font_shadow_draw(fs, rect->xmin+xofs, rect->ymin+yofs, str);
+
BLF_position(rect->xmin+xofs, rect->ymin+yofs, 0.0f);
-
- if (fs->shadow) {
- BLF_enable(BLF_SHADOW);
- BLF_shadow(fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
- BLF_shadow_offset(fs->shadx, fs->shady);
- }
-
- if (fs->overlap)
- BLF_enable(BLF_OVERLAP_CHAR);
-
BLF_draw(str);
+
BLF_disable(BLF_CLIPPING);
- if (fs->shadow)
- BLF_disable(BLF_SHADOW);
- if (fs->overlap)
- BLF_disable(BLF_OVERLAP_CHAR);
}
/* ************** helpers ************************ */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index b128da7b97f..15c0619e4e1 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: interface_templates.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -27,14 +27,9 @@
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-
#include "BLI_string.h"
#include "BKE_context.h"
-#include "BKE_icons.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_utildefines.h"
@@ -48,7 +43,6 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "interface_intern.h"
void ui_template_fix_linking()
{
@@ -64,55 +58,107 @@ void uiTemplateHeader(uiLayout *layout, bContext *C)
ED_area_header_standardbuttons(C, block, 0);
}
-/********************** Search Callbacks *************************/
+/******************* Header ID Template ************************/
typedef struct TemplateID {
PointerRNA ptr;
PropertyRNA *prop;
- ListBase *idlb;
+ int flag;
+ short browse;
+
+ char newop[256];
+ char openop[256];
+ char unlinkop[256];
+
+ short idtype;
} TemplateID;
-/* Search browse menu, assign */
-static void id_search_call_cb(struct bContext *C, void *arg_template, void *item)
+static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
{
- TemplateID *template= (TemplateID*)arg_template;
+ TemplateID *template= (TemplateID*)arg_litem;
+ PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
+ ID *id= idptr.data;
+ int event= GET_INT_FROM_POINTER(arg_event);
+
+ if(event == UI_ID_BROWSE && template->browse == 32767)
+ event= UI_ID_ADD_NEW;
+ else if(event == UI_ID_BROWSE && template->browse == 32766)
+ event= UI_ID_OPEN;
+
+ switch(event) {
+ case UI_ID_BROWSE:
+ printf("warning, id browse shouldnt come here\n");
+ break;
+ case UI_ID_DELETE:
+ memset(&idptr, 0, sizeof(idptr));
+ RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+ RNA_property_update(C, &template->ptr, template->prop);
+ break;
+ case UI_ID_FAKE_USER:
+ if(id) {
+ if(id->flag & LIB_FAKEUSER) id->us++;
+ else id->us--;
+ }
+ else return;
+ break;
+ case UI_ID_PIN:
+ break;
+ case UI_ID_ADD_NEW:
+ WM_operator_name_call(C, template->newop, WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case UI_ID_OPEN:
+ WM_operator_name_call(C, template->openop, WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+#if 0
+ case UI_ID_ALONE:
+ if(!id || id->us < 1)
+ return;
+ break;
+ case UI_ID_LOCAL:
+ if(!id || id->us < 1)
+ return;
+ break;
+ case UI_ID_AUTO_NAME:
+ break;
+#endif
+ }
+}
- /* ID */
+/* ID Search browse menu, assign */
+static void id_search_call_cb(struct bContext *C, void *arg_litem, void *item)
+{
if(item) {
- PointerRNA idptr;
+ TemplateID *template= (TemplateID*)arg_litem;
+ PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
RNA_id_pointer_create(item, &idptr);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
RNA_property_update(C, &template->ptr, template->prop);
- }
+ }
}
/* ID Search browse menu, do the search */
-static void id_search_cb(const struct bContext *C, void *arg_template, char *str, uiSearchItems *items)
+static void id_search_cb(const struct bContext *C, void *arg_litem, char *str, uiSearchItems *items)
{
- TemplateID *template= (TemplateID*)arg_template;
- Scene *scene= CTX_data_scene(C);
- ListBase *lb= template->idlb;
+ TemplateID *template= (TemplateID*)arg_litem;
+ ListBase *lb= wich_libbase(CTX_data_main(C), template->idtype);
ID *id;
- int iconid;
-
- /* ID listbase */
+
for(id= lb->first; id; id= id->next) {
- iconid= ui_id_icon_get(scene, id);
-
- if(BLI_strcasestr(id->name+2, str))
- if(!uiSearchItemAdd(items, id->name+2, id, iconid))
+
+ if(BLI_strcasestr(id->name+2, str)) {
+ if(0==uiSearchItemAdd(items, id->name+2, id))
break;
+ }
}
}
/* ID Search browse menu, open */
-static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
+static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
{
static char search[256];
static TemplateID template;
- PointerRNA idptr;
wmEvent event;
wmWindow *win= CTX_wm_window(C);
uiBlock *block;
@@ -123,9 +169,6 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* arg_litem is malloced, can be freed by parent button */
template= *((TemplateID*)arg_litem);
- /* get active id for showing first item */
- idptr= RNA_property_pointer_get(&template.ptr, template.prop);
-
block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
@@ -133,7 +176,7 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
- uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
+ uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb);
uiBoundsBlock(block, 6);
uiBlockSetDirection(block, UI_DOWN);
@@ -149,57 +192,17 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
return block;
}
-/************************ ID Template ***************************/
+/* ****************** */
-static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
-{
- TemplateID *template= (TemplateID*)arg_litem;
- PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
- ID *id= idptr.data;
- int event= GET_INT_FROM_POINTER(arg_event);
-
- switch(event) {
- case UI_ID_BROWSE:
- case UI_ID_PIN:
- case UI_ID_OPEN:
- case UI_ID_ADD_NEW:
- printf("warning, id event %d shouldnt come here\n", event);
- break;
- case UI_ID_DELETE:
- memset(&idptr, 0, sizeof(idptr));
- RNA_property_pointer_set(&template->ptr, template->prop, idptr);
- RNA_property_update(C, &template->ptr, template->prop);
- break;
- case UI_ID_FAKE_USER:
- if(id) {
- if(id->flag & LIB_FAKEUSER) id->us++;
- else id->us--;
- }
- else return;
- break;
-#if 0
- case UI_ID_ALONE:
- if(!id || id->us < 1)
- return;
- break;
- case UI_ID_LOCAL:
- if(!id || id->us < 1)
- return;
- break;
- case UI_ID_AUTO_NAME:
- break;
-#endif
- }
-}
-static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *unlinkop)
+static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type)
{
uiBut *but;
PointerRNA idptr;
ListBase *lb;
idptr= RNA_property_pointer_get(&template->ptr, template->prop);
- lb= template->idlb;
+ lb= wich_libbase(CTX_data_main(C), template->idtype);
if(idptr.type)
type= idptr.type;
@@ -207,8 +210,29 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
uiDefIconBut(block, LABEL, 0, RNA_struct_ui_icon(type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiBlockBeginAlign(block);
- if(flag & UI_ID_BROWSE)
- uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
+ if(template->flag & UI_ID_BROWSE) {
+ /*
+ char *extrastr, *str;
+
+ if((template->flag & UI_ID_ADD_NEW) && (template->flag & UI_ID_OPEN))
+ extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
+ else if(template->flag & UI_ID_ADD_NEW)
+ extrastr= "ADD NEW %x 32767";
+ else if(template->flag & UI_ID_OPEN)
+ extrastr= "OPEN NEW %x 32766";
+ else
+ extrastr= NULL;
+
+ duptemplate= MEM_dupallocN(template);
+ IDnames_to_pupstring(&str, NULL, extrastr, lb, idptr.data, &duptemplate->browse);
+
+ but= uiDefButS(block, MENU, 0, str, 0, 0, UI_UNIT_X, UI_UNIT_Y, &duptemplate->browse, 0, 0, 0, 0, "Browse existing choices, or add new");
+ uiButSetNFunc(but, template_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE));
+
+ MEM_freeN(str);
+ */
+ uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
+ }
/* text button with name */
if(idptr.data) {
@@ -220,11 +244,11 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
}
- if(flag & UI_ID_ADD_NEW) {
+ if(template->flag & UI_ID_ADD_NEW) {
int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
- if(newop) {
- but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+ if(template->newop[0]) {
+ but= uiDefIconTextButO(block, BUT, template->newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
}
else {
but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
@@ -233,9 +257,9 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
}
/* delete button */
- if(idptr.data && (flag & UI_ID_DELETE)) {
- if(unlinkop) {
- but= uiDefIconButO(block, BUT, unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ if(idptr.data && (template->flag & UI_ID_DELETE)) {
+ if(template->unlinkop[0]) {
+ but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
}
else {
but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
@@ -246,13 +270,12 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
uiBlockEndAlign(block);
}
-void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *unlinkop)
+void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
{
TemplateID *template;
uiBlock *block;
PropertyRNA *prop;
StructRNA *type;
- int flag;
if(!ptr->data)
return;
@@ -267,19 +290,26 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
template= MEM_callocN(sizeof(TemplateID), "TemplateID");
template->ptr= *ptr;
template->prop= prop;
+ template->flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
- flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
-
- if(newop)
- flag |= UI_ID_ADD_NEW;
+ if(newop) {
+ template->flag |= UI_ID_ADD_NEW;
+ BLI_strncpy(template->newop, newop, sizeof(template->newop));
+ }
+ if(openop) {
+ template->flag |= UI_ID_OPEN;
+ BLI_strncpy(template->openop, openop, sizeof(template->openop));
+ }
+ if(unlinkop)
+ BLI_strncpy(template->unlinkop, unlinkop, sizeof(template->unlinkop));
type= RNA_property_pointer_type(ptr, prop);
- template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
+ template->idtype = RNA_type_to_ID_code(type);
- if(template->idlb) {
+ if(template->idtype) {
uiLayoutRow(layout, 1);
block= uiLayoutGetBlock(layout);
- template_ID(C, block, template, type, flag, newop, unlinkop);
+ template_header_ID(C, block, template, type);
}
MEM_freeN(template);
@@ -332,15 +362,6 @@ static void modifiers_del(bContext *C, void *ob_v, void *md_v)
BKE_reports_clear(&reports);
}
-static void modifiers_activate(bContext *C, void *ob_v, void *md_v)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= ob_v;
-
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-}
-
static void modifiers_moveUp(bContext *C, void *ob_v, void *md_v)
{
Scene *scene= CTX_data_scene(C);
@@ -534,10 +555,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
uiBlockSetEmboss(block, UI_EMBOSSN);
uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
}
-
- /* modifier-type icon */
- uiDefIconBut(block, BUT, 0, RNA_struct_ui_icon(ptr.type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Current Modifier Type");
-
+
uiBlockSetEmboss(block, UI_EMBOSS);
if (isVirtual) {
@@ -548,16 +566,14 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
uiButSetFunc(but, modifiers_convertToReal, ob, md);
} else {
uiBlockBeginAlign(block);
- uiDefBut(block, TEX, 0, "", 0, 0, buttonWidth-40, UI_UNIT_Y, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name");
+ uiDefBut(block, TEX, 0, "", 0, 0, buttonWidth-60, UI_UNIT_Y, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name");
/* Softbody not allowed in this situation, enforce! */
if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
uiDefIconButBitI(block, TOG, eModifierMode_Render, 0, ICON_SCENE, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, 0, ICON_VIEW3D, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
- uiButSetFunc(but, modifiers_activate, ob, md);
if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
- but= uiDefIconButBitI(block, TOG, eModifierMode_Editmode, 0, ICON_EDITMODE_HLT, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
- uiButSetFunc(but, modifiers_activate, ob, md);
+ uiDefIconButBitI(block, TOG, eModifierMode_Editmode, 0, ICON_EDITMODE_HLT, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
}
}
uiBlockEndAlign(block);
@@ -1474,209 +1490,3 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
}
}
}
-
-
-/************************* List Template **************************/
-
-#if 0
-typedef struct ListItem {
- PointerRNA ptr;
- PropertyRNA *prop;
- PropertyRNA *activeprop;
-
- PointerRNA activeptr;
- int activei;
-
- int selected;
-} ListItem;
-
-static void list_item_cb(bContext *C, void *arg_item, void *arg_unused)
-{
- ListItem *item= (ListItem*)arg_item;
- PropertyType activetype;
- char *activename;
-
- if(item->selected) {
- activetype= RNA_property_type(item->activeprop);
-
- if(activetype == PROP_POINTER)
- RNA_property_pointer_set(&item->ptr, item->activeprop, item->activeptr);
- else if(activetype == PROP_INT)
- RNA_property_int_set(&item->ptr, item->activeprop, item->activei);
- else if(activetype == PROP_STRING) {
- activename= RNA_struct_name_get_alloc(&item->activeptr, NULL, 0);
- RNA_property_string_set(&item->ptr, item->activeprop, activename);
- MEM_freeN(activename);
- }
- }
-}
-#endif
-
-ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *activepropname, int rows, int columns, int compact)
-{
- CollectionPointerLink *link;
- PropertyRNA *prop, *activeprop;
- PropertyType type, activetype;
- PointerRNA activeptr;
- uiLayout *box, *row, *col;
- uiBlock *block;
- uiBut *but;
- ListBase lb;
- char *name, *activename= NULL, str[32];
- int i= 1, activei= 0, len, items, found;
- static int scroll = 1;
-
- lb.first= lb.last= NULL;
-
- /* validate arguments */
- if(!ptr->data)
- return lb;
-
- prop= RNA_struct_find_property(ptr, propname);
- if(!prop) {
- printf("uiTemplateList: property not found: %s\n", propname);
- return lb;
- }
-
- activeprop= RNA_struct_find_property(ptr, activepropname);
- if(!activeprop) {
- printf("uiTemplateList: property not found: %s\n", activepropname);
- return lb;
- }
-
- type= RNA_property_type(prop);
- if(type != PROP_COLLECTION) {
- printf("uiTemplateList: expected collection property.\n");
- return lb;
- }
-
- activetype= RNA_property_type(activeprop);
- if(!ELEM3(activetype, PROP_POINTER, PROP_INT, PROP_STRING)) {
- printf("uiTemplateList: expected pointer, integer or string property.\n");
- return lb;
- }
-
- /* get active data */
- if(activetype == PROP_POINTER)
- activeptr= RNA_property_pointer_get(ptr, activeprop);
- else if(activetype == PROP_INT)
- activei= RNA_property_int_get(ptr, activeprop);
- else if(activetype == PROP_STRING)
- activename= RNA_property_string_get_alloc(ptr, activeprop, NULL, 0);
-
- block= uiLayoutGetBlock(layout);
-
- if(compact) {
- /* compact layout */
- found= 0;
-
- row= uiLayoutRow(layout, 1);
-
- RNA_PROP_BEGIN(ptr, itemptr, prop) {
- if(activetype == PROP_POINTER)
- found= (activeptr.data == itemptr.data);
- else if(activetype == PROP_INT)
- found= (activei == i);
- else if(activetype == PROP_STRING)
- found= (strcmp(activename, name) == 0);
-
- if(found) {
- name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
- if(name) {
- uiItemL(row, name, RNA_struct_ui_icon(itemptr.type));
- MEM_freeN(name);
- }
-
- link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
- link->ptr= itemptr;
- BLI_addtail(&lb, link);
- }
-
- i++;
- }
- RNA_PROP_END;
-
- if(i == 1)
- uiItemL(row, "", 0);
-
- sprintf(str, "%d :", i-1);
- but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, ptr, activepropname, 0, 0, 0, 0, 0, "");
- if(i == 1)
- uiButSetFlag(but, UI_BUT_DISABLED);
- }
- else {
- if(rows == 0)
- rows= 5;
- if(columns == 0)
- columns= 1;
-
- items= rows*columns;
-
- box= uiLayoutBox(layout);
- row= uiLayoutRow(box, 0);
- col = uiLayoutColumn(row, 1);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
-
- len= RNA_property_collection_length(ptr, prop);
- scroll= MIN2(scroll, len-items+1);
- scroll= MAX2(scroll, 1);
-
- RNA_PROP_BEGIN(ptr, itemptr, prop) {
- if(i >= scroll && i<scroll+items) {
- name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
-
- if(name) {
-#if 0
- ListItem *item= MEM_callocN(sizeof(ListItem), "uiTemplateList ListItem");
-
- item->ptr= *ptr;
- item->prop= prop;
- item->activeprop= activeprop;
- item->activeptr= itemptr;
- item->activei= i;
-
- if(activetype == PROP_POINTER)
- item->selected= (activeptr.data == itemptr.data)? i: -1;
- else if(activetype == PROP_INT)
- item->selected= (activei == i)? i: -1;
- else if(activetype == PROP_STRING)
- item->selected= (strcmp(activename, name) == 0)? i: -1;
-#endif
-
- //but= uiDefIconTextButI(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, &item->selected, 0, i, 0, 0, "");
- but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, ptr, activepropname, 0/*&item->selected*/, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT);
- //uiButSetNFunc(but, list_item_cb, item, NULL);
-
- MEM_freeN(name);
-
- link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
- link->ptr= itemptr;
- BLI_addtail(&lb, link);
- }
- }
-
- i++;
- }
- RNA_PROP_END;
-
- while(i < scroll+items) {
- if(i >= scroll)
- uiItemL(col, "", 0);
- i++;
- }
-
- uiBlockSetEmboss(block, UI_EMBOSS);
-
- if(len > items) {
- col= uiLayoutColumn(row, 0);
- uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &scroll, 1, len-items+1, items, 0, "");
- }
-
- //uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*15,UI_UNIT_Y*0.75, &scroll, 1, 16-5, 5, 0, "");
- }
-
- return lb;
-}
-
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index eb79848d7d2..a75a3402774 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -43,7 +43,6 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
-#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -111,12 +110,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
break;
case PROP_STRING:
- if(icon && name && strcmp(name, "") == 0)
- but= uiDefIconButR(block, TEX, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
- else if(icon)
- but= uiDefIconTextButR(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
- else
- but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
break;
case PROP_POINTER: {
PointerRNA pptr;
@@ -126,8 +120,6 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
if(!pptr.type)
pptr.type= RNA_property_pointer_type(ptr, prop);
icon= RNA_struct_ui_icon(pptr.type);
- if(icon == ICON_DOT)
- icon= 0;
but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
break;
@@ -147,39 +139,69 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
return but;
}
-void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr, int columns)
+void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr)
{
- uiLayout *split, *col;
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *prop;
+ uiLayout *split;
char *name;
uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
- RNA_STRUCT_BEGIN(ptr, prop) {
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
+
if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
continue;
+ split = uiLayoutSplit(layout, 0.5f);
+
name= (char*)RNA_property_ui_name(prop);
- if(columns == 1) {
- col= uiLayoutColumn(layout, 1);
- uiItemL(col, name, 0);
- }
- else if(columns == 2) {
- split = uiLayoutSplit(layout, 0.5f);
+ uiItemL(uiLayoutColumn(split, 0), name, 0);
+ uiItemFullR(uiLayoutColumn(split, 0), "", 0, ptr, prop, -1, 0, 0, 0, 0);
+ }
- uiItemL(uiLayoutColumn(split, 0), name, 0);
- col= uiLayoutColumn(split, 0);
- }
+ RNA_property_collection_end(&iter);
+}
+/* temp call, single collumn, test for toolbar only */
+void uiDefAutoButsRNA_single(const bContext *C, uiLayout *layout, PointerRNA *ptr)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *prop;
+ uiLayout *col;
+ char *name;
+
+ uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
+
+ if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
+ continue;
+
+ name= (char*)RNA_property_ui_name(prop);
+ col= uiLayoutColumn(layout, 1);
+ uiItemL(col, name, 0);
+
/* temp hack to show normal button for spin/screw */
if(strcmp(name, "Axis")==0) {
- uiDefButR(uiLayoutGetBlock(col), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL);
+ uiDefButR(uiLayoutGetBlock(layout), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL);
}
else uiItemFullR(col, "", 0, ptr, prop, -1, 0, 0, 0, 0);
}
- RNA_STRUCT_END;
+
+ RNA_property_collection_end(&iter);
}
+
/***************************** ID Utilities *******************************/
/* note, C code version, will be replaced with version in interface_templates.c */
@@ -282,25 +304,9 @@ static void id_search_cb(const struct bContext *C, void *arg_params, char *str,
ID *id;
for(id= params->lb->first; id; id= id->next) {
- int iconid= 0;
-
-
- /* icon */
- switch(GS(id->name))
- {
- case ID_MA: /* fall through */
- case ID_TE: /* fall through */
- case ID_IM: /* fall through */
- case ID_WO: /* fall through */
- case ID_LA: /* fall through */
- iconid= BKE_icon_getid(id);
- break;
- default:
- break;
- }
if(BLI_strcasestr(id->name+2, str)) {
- if(0==uiSearchItemAdd(items, id->name+2, id, iconid))
+ if(0==uiSearchItemAdd(items, id->name+2, id))
break;
}
}
@@ -327,7 +333,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_params)
uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
- uiButSetSearchFunc(but, id_search_cb, &params, id_search_call_cb, NULL);
+ uiButSetSearchFunc(but, id_search_cb, &params, id_search_call_cb);
uiBoundsBlock(block, 6);
uiBlockSetDirection(block, UI_DOWN);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ddf31c0db66..14df9026078 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -102,7 +102,6 @@ typedef struct uiWidgetBase {
float inner_uv[64][2];
short inner, outline, emboss; /* set on/off */
- short shadedir;
uiWidgetTrias tria1;
uiWidgetTrias tria2;
@@ -200,7 +199,6 @@ static void widget_init(uiWidgetBase *wtb)
wtb->inner= 1;
wtb->outline= 1;
wtb->emboss= 1;
- wtb->shadedir= 1;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -585,7 +583,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glShadeModel(GL_SMOOTH);
glBegin(GL_POLYGON);
for(a=0; a<wtb->totvert; a++) {
- round_box_shade_col4(col1, col2, wtb->inner_uv[a][wtb->shadedir]);
+ round_box_shade_col4(col1, col2, wtb->inner_uv[a][1]);
glVertex2fv(wtb->inner_v[a]);
}
glEnd();
@@ -1028,7 +1026,7 @@ static struct uiWidgetColors wcol_menu_back= {
{0, 0, 0, 255},
{25, 25, 25, 230},
{45, 45, 45, 230},
- {100, 100, 100, 255},
+ {255, 255, 255, 255},
{255, 255, 255, 255},
{255, 255, 255, 255},
@@ -1090,32 +1088,6 @@ static struct uiWidgetColors wcol_box= {
0, 0
};
-static struct uiWidgetColors wcol_toggle= {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-static struct uiWidgetColors wcol_scroll= {
- {25, 25, 25, 255},
- {180, 180, 180, 255},
- {153, 153, 153, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 0, -20
-};
-
/* free wcol struct to play with */
static struct uiWidgetColors wcol_tmp= {
{0, 0, 0, 255},
@@ -1137,10 +1109,9 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_regular= wcol_regular;
tui->wcol_tool= wcol_tool;
- tui->wcol_text= wcol_text;
tui->wcol_radio= wcol_radio;
+ tui->wcol_text= wcol_text;
tui->wcol_option= wcol_option;
- tui->wcol_toggle= wcol_toggle;
tui->wcol_num= wcol_num;
tui->wcol_numslider= wcol_numslider;
tui->wcol_menu= wcol_menu;
@@ -1148,7 +1119,6 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_menu_back= wcol_menu_back;
tui->wcol_menu_item= wcol_menu_item;
tui->wcol_box= wcol_box;
- tui->wcol_scroll= wcol_scroll;
}
/* ************ button callbacks, state ***************** */
@@ -1632,75 +1602,6 @@ void ui_draw_link_bezier(rcti *rect)
}
}
-static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
-{
- uiWidgetBase wtb;
- rcti rect1;
- double value;
- char inner[3];
- float fac, size, rad;
- int horizontal;
-
- /* determine horizontal/vertical */
- horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
-
- if(horizontal)
- rad= 0.5f*(rect->ymax - rect->ymin);
- else
- rad= 0.5f*(rect->xmax - rect->xmin);
-
- widget_init(&wtb);
- wtb.shadedir= (horizontal)? 1: 0;
-
- /* draw back part, colors swapped and shading inverted */
- VECCOPY(inner, wcol->inner);
- VECCOPY(wcol->inner, wcol->item);
- if(horizontal)
- SWAP(short, wcol->shadetop, wcol->shadedown);
- if(state & UI_SELECT)
- SWAP(short, wcol->shadetop, wcol->shadedown);
-
- round_box_edges(&wtb, roundboxalign, rect, rad); /* XXX vertical gradient is wrong */
- widgetbase_draw(&wtb, wcol);
-
- VECCOPY(wcol->inner, inner);
- if(horizontal)
- SWAP(short, wcol->shadetop, wcol->shadedown);
- if(state & UI_SELECT)
- SWAP(short, wcol->shadetop, wcol->shadedown);
-
- /* front part */
- value= ui_get_but_val(but);
-
- size= (but->softmax + but->a1 - but->softmin);
- size= MAX2(size, 2);
-
- /* position */
- rect1= *rect;
-
- if(horizontal) {
- fac= (rect->xmax - rect->xmin)/(size-1);
- rect1.xmin= rect1.xmin + ceil(fac*(value - but->softmin));
- rect1.xmax= rect1.xmin + ceil(fac*(but->a1 - but->softmin));
- }
- else {
- fac= (rect->ymax - rect->ymin)/(size-1);
- rect1.ymax= rect1.ymax - ceil(fac*(value - but->softmin));
- rect1.ymin= rect1.ymax - ceil(fac*(but->a1 - but->softmin));
- }
-
- /* draw */
- wtb.emboss= 0; /* only emboss once */
-
- if(!horizontal)
- SWAP(short, wcol->shadetop, wcol->shadedown);
-
- round_box_edges(&wtb, roundboxalign, &rect1, rad); /* XXX vertical gradient is wrong */
- widgetbase_draw(&wtb, wcol);
-
- if(!horizontal)
- SWAP(short, wcol->shadetop, wcol->shadedown);
-}
static void widget_link(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
@@ -1995,16 +1896,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.text= widget_draw_text_icon;
switch(type) {
- case UI_WTYPE_REGULAR:
- break;
-
case UI_WTYPE_LABEL:
wt.draw= NULL;
wt.state= widget_state_label;
break;
case UI_WTYPE_TOGGLE:
- wt.wcol_theme= &btheme->tui.wcol_toggle;
break;
case UI_WTYPE_OPTION:
@@ -2017,7 +1914,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.wcol_theme= &btheme->tui.wcol_radio;
wt.draw= widget_radiobut;
break;
-
+
case UI_WTYPE_NUMBER:
wt.wcol_theme= &btheme->tui.wcol_num;
wt.draw= widget_numbut;
@@ -2098,11 +1995,6 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_NORMAL:
break;
-
- case UI_WTYPE_SCROLL:
- wt.wcol_theme= &btheme->tui.wcol_scroll;
- wt.custom= widget_scroll;
- break;
}
return &wt;
@@ -2197,7 +2089,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case BUT:
wt= widget_type(UI_WTYPE_EXEC);
break;
-
case NUM:
wt= widget_type(UI_WTYPE_NUMBER);
break;
@@ -2293,13 +2184,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case BUT_CURVE:
ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
break;
-
- case SCROLL:
- wt= widget_type(UI_WTYPE_SCROLL);
- break;
-
+
default:
- wt= widget_type(UI_WTYPE_REGULAR);
+ wt= widget_type(UI_WTYPE_TOGGLE);
}
}
@@ -2308,7 +2195,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
int roundboxalign, state;
roundboxalign= widget_roundbox_set(but, rect);
-
state= but->flag;
if(but->editstr) state |= UI_TEXTINPUT;
@@ -2356,7 +2242,7 @@ void ui_draw_search_back(uiStyle *style, uiBlock *block, rcti *rect)
/* helper call to draw a menu item without button */
/* state: UI_ACTIVE or 0 */
-void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state)
+void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
{
uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
rcti _rect= *rect;
@@ -2370,7 +2256,6 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid,
/* text location offset */
rect->xmin+=5;
- if(iconid) rect->xmin+= ICON_HEIGHT;
/* cut string in 2 parts? */
cpoin= strchr(name, '|');
@@ -2393,12 +2278,5 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid,
/* restore rect, was messed with */
*rect= _rect;
- if(iconid) {
- int xs= rect->xmin+4;
- int ys= 1 + (rect->ymin+rect->ymax- ICON_HEIGHT)/2;
- glEnable(GL_BLEND);
- UI_icon_draw_aspect_blended(xs, ys, iconid, 1.2f, 0); /* XXX scale weak get from fstyle? */
- glDisable(GL_BLEND);
- }
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index f83dee23417..0a65718b708 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: resources.c 12755 2007-12-02 05:50:38Z aligorith $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index aa5aa65d300..189898cc907 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: view2d.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -316,12 +316,6 @@ void UI_view2d_curRect_validate(View2D *v2d)
if (v2d->keepzoom & V2D_LOCKZOOM_Y)
height= winy;
- /* values used to divide, so make it safe */
- if(width<1) width= 1;
- if(height<1) height= 1;
- if(winx<1) winx= 1;
- if(winy<1) winy= 1;
-
/* keepzoom (V2D_KEEPZOOM set), indicates that zoom level on each axis must not exceed limits
* NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
*/
diff --git a/source/blender/editors/mesh/Makefile b/source/blender/editors/mesh/Makefile
index 8ae40e1b957..650771519cd 100644
--- a/source/blender/editors/mesh/Makefile
+++ b/source/blender/editors/mesh/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index 7f5201f4704..dd003d103d5 100644
--- a/source/blender/editors/mesh/editmesh.c
+++ b/source/blender/editors/mesh/editmesh.c
@@ -841,7 +841,7 @@ void make_editMesh(Scene *scene, Object *ob)
em= me->edit_mesh;
- em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
+ em->selectmode= scene->selectmode; // warning needs to be synced
em->act_face = NULL;
em->totvert= tot= me->totvert;
em->totedge= me->totedge;
@@ -1556,7 +1556,7 @@ static int mesh_separate_material(Scene *scene, Base *editbase)
/* clear selection, we're going to use that to select material group */
EM_clear_flag_all(em, SELECT);
/* select the material */
- EM_select_by_material(em, curr_mat);
+ editmesh_select_by_material(em, curr_mat);
/* and now separate */
if(0==mesh_separate_selected(scene, editbase)) {
BKE_mesh_end_editmesh(me, em);
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 12138ee13d2..57fb2c19c75 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -1276,7 +1276,7 @@ static float new_primitive_matrix(bContext *C, float primmat[][4])
Object *obedit= CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d =CTX_wm_view3d(C);
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
float *curs, mat[3][3], vmat[3][3], cmat[3][3], imat[3][3];
Mat4One(primmat);
@@ -1295,9 +1295,9 @@ static float new_primitive_matrix(bContext *C, float primmat[][4])
/* center */
curs= give_cursor(scene, v3d);
VECCOPY(primmat[3], curs);
- VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
Mat3Inv(imat, mat);
Mat3MulVecfl(imat, primmat[3]);
+ VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
if(v3d) return v3d->grid;
return 1.0f;
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
index 70a0c6b82da..a1f8b3251c8 100644
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -3242,7 +3242,7 @@ static int toggle_select_all_exec(bContext *C, wmOperator *op)
void MESH_OT_select_all_toggle(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Select/Deselect All";
+ ot->name= "Select or Deselect All";
ot->idname= "MESH_OT_select_all_toggle";
/* api callbacks */
@@ -3484,7 +3484,7 @@ void MESH_OT_select_random(wmOperatorType *ot)
RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f);
}
-void EM_select_by_material(EditMesh *em, int index)
+void editmesh_select_by_material(EditMesh *em, int index)
{
EditFace *efa;
@@ -3497,7 +3497,7 @@ void EM_select_by_material(EditMesh *em, int index)
EM_selectmode_flush(em);
}
-void EM_deselect_by_material(EditMesh *em, int index)
+void editmesh_deselect_by_material(EditMesh *em, int index)
{
EditFace *efa;
@@ -3531,7 +3531,7 @@ static void mesh_selection_type(Scene *scene, EditMesh *em, int val)
/* note, em stores selectmode to be able to pass it on everywhere without scene,
this is only until all select modes and toolsettings are settled more */
- scene->toolsettings->selectmode= em->selectmode;
+ scene->selectmode= em->selectmode;
// if (EM_texFaceCheck())
}
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index dc9c8c6b6d2..b26fded4fb6 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -787,7 +787,7 @@ static int extrude_repeat_mesh(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
int steps = RNA_int_get(op->ptr,"steps");
@@ -949,7 +949,7 @@ static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]);
@@ -1056,7 +1056,7 @@ static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]);
diff --git a/source/blender/editors/object/Makefile b/source/blender/editors/object/Makefile
index 70ada46c80f..c0312023bfd 100644
--- a/source/blender/editors/object/Makefile
+++ b/source/blender/editors/object/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index c436ccdb328..74a1fc12631 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -340,7 +340,7 @@ static int object_add_mesh_exec(bContext *C, wmOperator *op)
if(obedit==NULL || obedit->type!=OB_MESH) {
object_add_type(C, OB_MESH);
- ED_object_enter_editmode(C, EM_DO_UNDO);
+ ED_object_enter_editmode(C, 0);
newob = 1;
}
else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
@@ -388,7 +388,7 @@ static int object_add_mesh_exec(bContext *C, wmOperator *op)
void OBJECT_OT_mesh_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Mesh";
+ ot->name= "Mesh";
ot->description = "Add a mesh object to the scene.";
ot->idname= "OBJECT_OT_mesh_add";
@@ -398,8 +398,8 @@ void OBJECT_OT_mesh_add(wmOperatorType *ot)
ot->poll= ED_operator_scene_editable;
- /* flags: no register or undo, this operator calls operators */
- ot->flag= 0; //OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag= 0;
RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
}
@@ -462,7 +462,7 @@ static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
void OBJECT_OT_curve_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Curve";
+ ot->name= "Curve";
ot->description = "Add a curve object to the scene.";
ot->idname= "OBJECT_OT_curve_add";
@@ -520,7 +520,7 @@ static int object_add_surface_exec(bContext *C, wmOperator *op)
void OBJECT_OT_surface_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Surface";
+ ot->name= "Surface";
ot->description = "Add a surface object to the scene.";
ot->idname= "OBJECT_OT_surface_add";
@@ -557,7 +557,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
void OBJECT_OT_text_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Text";
+ ot->name= "Text";
ot->description = "Add a text object to the scene";
ot->idname= "OBJECT_OT_text_add";
@@ -602,7 +602,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
void OBJECT_OT_armature_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Armature";
+ ot->name= "Armature";
ot->description = "Add an armature object to the scene.";
ot->idname= "OBJECT_OT_armature_add";
@@ -1395,8 +1395,7 @@ static int parent_clear_exec(bContext *C, wmOperator *op)
DAG_scene_sort(CTX_data_scene(C));
ED_anim_dag_flush_update(C);
- WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -2601,8 +2600,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
DAG_scene_sort(CTX_data_scene(C));
- ED_anim_dag_flush_update(C);
- WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+ ED_anim_dag_flush_update(C);
return OPERATOR_FINISHED;
}
@@ -2650,7 +2648,7 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
ot->poll= ED_operator_object_active;
/* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ ot->flag= 0;
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
@@ -3351,7 +3349,6 @@ void ED_object_enter_editmode(bContext *C, int flag)
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
}
- if(flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
if(flag & EM_WAITCURSOR) waitcursor(0);
}
@@ -3664,7 +3661,7 @@ void special_editmenu(Scene *scene, View3D *v3d)
if(!psys)
return;
- if(pset->selectmode & SCE_SELECT_POINT)
+ if(scene->selectmode & SCE_SELECT_POINT)
nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4|Remove Doubles%x5");
else
nr= pupmenu("Specials%t|Rekey%x1|Remove Doubles%x5");
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 4bcfcc4d5ab..ee506220b67 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: object_modifier.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/physics/Makefile b/source/blender/editors/physics/Makefile
index 63968fdd537..a71ea9e2083 100644
--- a/source/blender/editors/physics/Makefile
+++ b/source/blender/editors/physics/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c
index 1b6b5b43522..b6625cb387c 100644
--- a/source/blender/editors/physics/editparticle.c
+++ b/source/blender/editors/physics/editparticle.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: editparticle.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -225,7 +225,7 @@ void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra)
ParticleEditSettings *pset=PE_settings(scene);
int i, k, totpart= psys->totpart;
- if(pset->draw_timed && pset->selectmode==SCE_SELECT_POINT) {
+ if(pset->draw_timed && scene->selectmode==SCE_SELECT_POINT) {
LOOP_PARTICLES(i, pa) {
LOOP_KEYS(k, key) {
if(fabs(cfra-*key->time) < pset->draw_timed)
@@ -425,12 +425,11 @@ static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
ParticleEdit *edit= psys->edit;
ParticleData *pa;
ParticleEditKey *key;
- ParticleEditSettings *pset= PE_settings(data->scene);
int i, k, totpart, nearest_pa, nearest_key;
float dist= data->rad;
/* in path select mode we have no keys */
- if(pset->selectmode==SCE_SELECT_PATH)
+ if(data->scene->selectmode==SCE_SELECT_PATH)
return;
totpart= psys->totpart;
@@ -440,7 +439,7 @@ static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
LOOP_PARTICLES(i, pa) {
if(pa->flag & PARS_HIDE) continue;
- if(pset->selectmode == SCE_SELECT_END) {
+ if(data->scene->selectmode == SCE_SELECT_END) {
/* only do end keys */
key= edit->keys[i] + pa->totkey-1;
@@ -482,19 +481,18 @@ static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int s
ParticleSystem *psys= data->psys;
ParticleData *pa;
ParticleEditKey *key;
- ParticleEditSettings *pset= PE_settings(data->scene);
int i, k, totpart;
totpart= psys->totpart;
/* all is selected in path mode */
- if(pset->selectmode==SCE_SELECT_PATH)
+ if(data->scene->selectmode==SCE_SELECT_PATH)
selected=0;
LOOP_PARTICLES(i, pa) {
if(pa->flag & PARS_HIDE) continue;
- if(pset->selectmode==SCE_SELECT_END) {
+ if(data->scene->selectmode==SCE_SELECT_END) {
/* only do end keys */
key= psys->edit->keys[i] + pa->totkey-1;
@@ -524,7 +522,6 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
ParticleData *pa;
ParticleEditKey *key;
ParticleSystemModifierData *psmd=0;
- ParticleEditSettings *pset= PE_settings(data->scene);
int i, k, totpart;
float mat[4][4], imat[4][4];
@@ -532,7 +529,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
totpart= psys->totpart;
/* all is selected in path mode */
- if(pset->selectmode==SCE_SELECT_PATH)
+ if(data->scene->selectmode==SCE_SELECT_PATH)
selected= 0;
Mat4One(imat);
@@ -544,7 +541,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
Mat4Invert(imat,mat);
- if(pset->selectmode==SCE_SELECT_END) {
+ if(data->scene->selectmode==SCE_SELECT_END) {
/* only do end keys */
key= psys->edit->keys[i] + pa->totkey-1;
@@ -613,7 +610,6 @@ static int count_selected_keys(Scene *scene, ParticleSystem *psys)
{
ParticleData *pa;
ParticleEditKey *key;
- ParticleEditSettings *pset= PE_settings(scene);
int i, k, totpart, sel= 0;
totpart= psys->totpart;
@@ -623,12 +619,12 @@ static int count_selected_keys(Scene *scene, ParticleSystem *psys)
key= psys->edit->keys[i];
- if(pset->selectmode==SCE_SELECT_POINT) {
+ if(scene->selectmode==SCE_SELECT_POINT) {
for(k=0; k<pa->totkey; k++,key++)
if(key->flag & PEK_SELECT)
sel++;
}
- else if(pset->selectmode==SCE_SELECT_END) {
+ else if(scene->selectmode==SCE_SELECT_END) {
key += pa->totkey-1;
if(key->flag & PEK_SELECT)
@@ -1458,7 +1454,6 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
ParticleEdit *edit;
ParticleData *pa;
ParticleEditKey *key;
- ParticleEditSettings *pset= PE_settings(scene);
float co[3], mat[4][4];
short vertco[2];
int i, k, totpart;
@@ -1475,7 +1470,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
- if(pset->selectmode==SCE_SELECT_POINT) {
+ if(scene->selectmode==SCE_SELECT_POINT) {
LOOP_KEYS(k, key) {
VECCOPY(co, key->co);
Mat4MulVecfl(mat, co);
@@ -1492,7 +1487,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
}
}
}
- else if(pset->selectmode==SCE_SELECT_END) {
+ else if(scene->selectmode==SCE_SELECT_END) {
key= edit->keys[i] + pa->totkey - 1;
VECCOPY(co, key->co);
@@ -2354,7 +2349,7 @@ enum { DEL_PARTICLE, DEL_KEY };
static EnumPropertyItem delete_type_items[]= {
{DEL_PARTICLE, "PARTICLE", 0, "Particle", ""},
{DEL_KEY, "KEY", 0, "Key", ""},
- {0, NULL, 0, NULL, NULL}};
+ {0, NULL, NULL}};
static void set_delete_particle(PEData *data, int pa_index)
{
@@ -3847,7 +3842,6 @@ void PE_change_act_psys(Scene *scene, Object *ob, ParticleSystem *psys)
static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Scene *scene= CTX_data_scene(C);
- ParticleEditSettings *pset=PE_settings(scene);
uiPopupMenu *pup;
uiLayout *layout;
@@ -3855,7 +3849,7 @@ static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
layout= uiPupMenuLayout(pup);
uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey");
- if(pset->selectmode & SCE_SELECT_POINT) {
+ if(scene->selectmode & SCE_SELECT_POINT) {
uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide");
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first");
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last");
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index e03649575cb..cbc94b3a058 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: physics_intern.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/preview/Makefile b/source/blender/editors/preview/Makefile
index 48e1dc64673..c44da6753f3 100644
--- a/source/blender/editors/preview/Makefile
+++ b/source/blender/editors/preview/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/preview/previewrender.c b/source/blender/editors/preview/previewrender.c
index 1efa5108b96..1ce20fcb0af 100644
--- a/source/blender/editors/preview/previewrender.c
+++ b/source/blender/editors/preview/previewrender.c
@@ -114,12 +114,46 @@ typedef struct ShaderPreview {
ID *id;
int sizex, sizey;
- int *pr_rect;
int pr_method;
} ShaderPreview;
+static void set_previewrect(ScrArea *sa, RenderInfo *ri)
+{
+ ARegion *ar= NULL; // XXX
+ rctf viewplane;
+
+ BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
+
+// ui_graphics_to_window_rct(ar->win, &viewplane, &ri->disprect);
+
+ /* correction for gla draw */
+ BLI_translate_rcti(&ri->disprect, -ar->winrct.xmin, -ar->winrct.ymin);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glaDefine2DArea(&ar->winrct);
+
+ ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
+ ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
+}
+
+static void end_previewrect(ARegion *ar)
+{
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ // restore viewport / scissor which was set by glaDefine2DArea
+ glViewport(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
+
+}
/* unused now */
void draw_tex_crop(Tex *tex)
@@ -404,6 +438,196 @@ static Scene *preview_prepare_scene(Scene *scene, int id_type, ShaderPreview *sp
return NULL;
}
+void previewrender_progress(void *handle, RenderResult *rr, volatile rcti *renrect)
+{
+ SpaceButs *sbuts= NULL; // XXX
+ RenderLayer *rl;
+ RenderInfo *ri= sbuts->ri;
+ float ofsx, ofsy;
+
+ if(renrect) return;
+
+ rl= rr->layers.first;
+
+ ofsx= ri->disprect.xmin + rr->tilerect.xmin;
+ ofsy= ri->disprect.ymin + rr->tilerect.ymin;
+
+ glDrawBuffer(GL_FRONT);
+ glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
+ bglFlush();
+ glDrawBuffer(GL_BACK);
+}
+
+
+/* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
+void BIF_previewrender(Scene *scene, struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
+{
+ SpaceButs *sbuts= NULL; // XXX
+ Render *re;
+ RenderStats *rstats;
+ Scene *sce;
+ int oldx= ri->pr_rectx, oldy= ri->pr_recty;
+ char name [32];
+
+ if(ri->tottile && ri->curtile>=ri->tottile) return;
+
+ /* check for return with a new event */
+ if(pr_method!=PR_ICON_RENDER && qtest()) {
+// if(area)
+// addafterqueue(area->win, RENDERPREVIEW, 1);
+ return;
+ }
+
+ /* get the stuff from the builtin preview dbase */
+// sce= preview_prepare_scene(scene, ri, GS(id->name), id, pr_method);
+ if(sce==NULL) return;
+
+ /* set drawing conditions OK */
+ if(area) {
+ sbuts= area->spacedata.first; /* needed for flag */
+
+ set_previewrect(area, ri); // uses UImat
+
+ /* because preview render size can differs */
+ if(ri->rect && (oldx!=ri->pr_rectx || oldy!=ri->pr_recty)) {
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ ri->curtile= 0;
+ }
+ }
+
+// XXX sprintf(name, "ButsPreview %d", area?area->win:0);
+ re= RE_GetRender(name);
+
+ /* full refreshed render from first tile */
+ if(re==NULL || ri->curtile==0) {
+
+ re= RE_NewRender(name);
+
+ /* handle cases */
+ if(pr_method==PR_DRAW_RENDER) {
+// RE_display_draw_cb(re, previewrender_progress);
+// RE_test_break_cb(re, qtest);
+ sce->r.scemode |= R_NODE_PREVIEW;
+ if(sbuts->flag & SB_PRV_OSA)
+ sce->r.mode |= R_OSA;
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+ }
+ else if(pr_method==PR_DO_RENDER) {
+// RE_test_break_cb(re, qtest);
+ sce->r.scemode |= R_NODE_PREVIEW;
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+ }
+ else { /* PR_ICON_RENDER */
+ sce->r.scemode &= ~R_NODE_PREVIEW;
+ sce->r.scemode |= R_NO_IMAGE_LOAD;
+ }
+
+ /* allocates render result */
+ RE_InitState(re, NULL, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
+
+ /* enforce preview image clear */
+ if(GS(id->name)==ID_MA) {
+ Material *ma= (Material *)id;
+ ntreeClearPreview(ma->nodetree);
+ }
+ }
+ /* entire cycle for render engine */
+ RE_SetCamera(re, sce->camera);
+ RE_Database_FromScene(re, sce, 1);
+ RE_TileProcessor(re, ri->curtile, 0); // actual render engine
+ RE_Database_Free(re);
+
+ /* handle results */
+ if(pr_method==PR_ICON_RENDER) {
+ if(ri->rect==NULL)
+ ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ RE_ResultGet32(re, ri->rect);
+ }
+ else {
+ rstats= RE_GetStats(re);
+
+ if(rstats->partsdone!=ri->curtile) {
+ if(ri->rect==NULL)
+ ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ RE_ResultGet32(re, ri->rect);
+ }
+
+ if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
+ // allqueues
+ }
+ else {
+// if(pr_method==PR_DRAW_RENDER && qtest())
+// addafterqueue(area->win, RENDERPREVIEW, 1);
+ }
+
+ ri->curtile= rstats->partsdone;
+ ri->tottile= rstats->totpart;
+ }
+
+ /* unassign the pointers, reset vars */
+// preview_prepare_scene(scene, ri, GS(id->name), NULL, 0);
+
+}
+
+
+/* afterqueue call */
+void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
+{
+// ScrArea *sa= NULL; // XXX
+ ARegion *ar= NULL; // XXX
+ uiBlock *block;
+ struct ID* id = 0;
+// struct ID* idfrom = 0;
+ struct ID* idshow = 0;
+ Object *ob;
+
+ if (!sbuts->ri) return;
+
+
+// block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
+ if(block==NULL) return;
+
+ ob= ((scene->basact)? (scene->basact)->object: 0);
+
+ /* we cant trust this global lockpoin.. for example with headerless window */
+// buttons_active_id(&id, &idfrom);
+ sbuts->lockpoin= id;
+
+ if(sbuts->mainb==CONTEXT_SHADING) {
+ int tab= TAB_SHADING_MAT; // XXX sbuts->tab[CONTEXT_SHADING];
+
+ if(tab==TAB_SHADING_MAT)
+ idshow = sbuts->lockpoin;
+ else if(tab==TAB_SHADING_TEX)
+ idshow = sbuts->lockpoin;
+ else if(tab==TAB_SHADING_LAMP) {
+ if(ob && ob->type==OB_LAMP) idshow= ob->data;
+ }
+ else if(tab==TAB_SHADING_WORLD)
+ idshow = sbuts->lockpoin;
+ }
+ else if(sbuts->mainb==CONTEXT_OBJECT) {
+ if(ob && ob->type==OB_LAMP) idshow = ob->data;
+ }
+
+ if (idshow) {
+ BKE_icon_changed(BKE_icon_getid(idshow));
+// uiPanelPush(block);
+// BIF_previewrender(scene, idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
+// uiPanelPop(block);
+ end_previewrect(ar);
+ }
+ else {
+ /* no active block to draw. But we do draw black if possible */
+ if(sbuts->ri->rect) {
+ memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
+ sbuts->ri->tottile= 10000;
+// addqueue(sa->win, REDRAW, 1);
+ }
+ return;
+ }
+}
/* new UI convention: draw is in pixel space already. */
/* uses ROUNDBOX button in block to get the rect */
@@ -782,7 +1006,7 @@ static void shader_preview_updatejob(void *spv)
}
-/* runs inside thread for material, in foreground for icons */
+/* runs inside thread */
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
{
ShaderPreview *sp= customdata;
@@ -840,8 +1064,9 @@ static void shader_preview_startjob(void *customdata, short *stop, short *do_upd
/* handle results */
if(sp->pr_method==PR_ICON_RENDER) {
- if(sp->pr_rect)
- RE_ResultGet32(re, sp->pr_rect);
+ //if(ri->rect==NULL)
+ // ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ //RE_ResultGet32(re, ri->rect);
}
else {
/* validate owner */
@@ -888,29 +1113,6 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, in
WM_jobs_callbacks(steve, shader_preview_startjob, NULL, shader_preview_updatejob);
WM_jobs_start(CTX_wm_manager(C), steve);
-
- /* signal to rerender icon in menus */
- BKE_icon_changed(BKE_icon_getid(id));
}
-/* rect should be allocated, sizex/sizy pixels, 32 bits */
-void ED_preview_iconrender(Scene *scene, ID *id, int *rect, int sizex, int sizey)
-{
- ShaderPreview *sp= MEM_callocN(sizeof(ShaderPreview), "ShaderPreview");
- short stop=0, do_update=0;
-
- /* customdata for preview thread */
- sp->scene= scene;
- sp->sizex= sizex;
- sp->sizey= sizey;
- sp->pr_method= PR_ICON_RENDER;
- sp->pr_rect= rect;
- sp->id = id;
-
- shader_preview_startjob(sp, &stop, &do_update);
-
- MEM_freeN(sp);
-}
-
-
diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile
index 923a020afcf..cf6e692c304 100644
--- a/source/blender/editors/screen/Makefile
+++ b/source/blender/editors/screen/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 535e99ccfef..07d8fb370e6 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -259,16 +259,14 @@ static void region_scissor_winrct(ARegion *ar, rcti *winrct)
while(ar->prev) {
ar= ar->prev;
- if(BLI_isect_rcti(winrct, &ar->winrct, NULL)) {
- if(ar->flag & RGN_FLAG_HIDDEN);
- else if(ar->alignment==RGN_OVERLAP_LEFT) {
- winrct->xmin= ar->winrct.xmax + 1;
- }
- else if(ar->alignment==RGN_OVERLAP_RIGHT) {
- winrct->xmax= ar->winrct.xmin - 1;
- }
- else break;
+ if(ar->flag & RGN_FLAG_HIDDEN);
+ else if(ar->alignment==RGN_OVERLAP_LEFT) {
+ winrct->xmin= ar->winrct.xmax + 1;
+ }
+ else if(ar->alignment==RGN_OVERLAP_RIGHT) {
+ winrct->xmax= ar->winrct.xmin - 1;
}
+ else break;
}
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index a23487effa1..a81a52fd544 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: glutil.c 11920 2007-09-02 17:25:03Z elubie $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index dcfdfbf8285..2aa6758850e 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -59,7 +59,6 @@
#include "ED_util.h"
#include "ED_screen.h"
#include "ED_mesh.h"
-#include "ED_object.h"
#include "ED_screen_types.h"
#include "RE_pipeline.h"
@@ -2510,9 +2509,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* flush multires changes (for sculpt) */
multires_force_update(CTX_data_active_object(C));
- /* get editmode results */
- ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
-
+ // get editmode results
// store spare
// get view3d layer, local layer, make this nice api call to render
// store spare
diff --git a/source/blender/editors/sculpt_paint/Makefile b/source/blender/editors/sculpt_paint/Makefile
index 012a39b8d25..9353116a4bc 100644
--- a/source/blender/editors/sculpt_paint/Makefile
+++ b/source/blender/editors/sculpt_paint/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 8f0b52ef3a1..fa33e214737 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: sculptmode.c 18309 2009-01-04 07:47:11Z nicholasbishop $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -148,7 +148,6 @@ typedef struct StrokeCache {
float *layer_disps; /* Displacements for each vertex */
float (*mesh_store)[3]; /* Copy of the mesh vertices' locations */
short (*orig_norms)[3]; /* Copy of the mesh vertices' normals */
- float (*face_norms)[3]; /* Copy of the mesh faces' normals */
float rotation; /* Texture rotation (radians) for anchored and rake modes */
int pixel_radius, previous_pixel_radius;
ListBase grab_active_verts[8]; /* The same list of verts is used throught grab stroke */
@@ -241,6 +240,7 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
float dir= sd->brush->flag & BRUSH_DIR_IN ? -1 : 1;
float pressure= 1;
float flip= cache->flip ? -1:1;
+ float anchored = sd->brush->flag & BRUSH_ANCHORED ? 25 : 1;
if(sd->brush->flag & BRUSH_ALPHA_PRESSURE)
pressure *= cache->pressure;
@@ -250,7 +250,6 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
case SCULPT_TOOL_INFLATE:
case SCULPT_TOOL_CLAY:
case SCULPT_TOOL_FLATTEN:
- case SCULPT_TOOL_LAYER:
return alpha * dir * pressure * flip; /*XXX: not sure why? was multiplied by G.vd->grid */;
case SCULPT_TOOL_SMOOTH:
return alpha * 4 * pressure;
@@ -258,27 +257,46 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
return alpha / 2 * dir * pressure * flip;
case SCULPT_TOOL_GRAB:
return 1;
+ case SCULPT_TOOL_LAYER:
+ return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */;
default:
return 0;
}
}
-/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */
-static void sculpt_clip(Sculpt *sd, float *co, const float val[3])
+/* For clipping against a mirror modifier */
+static void sculpt_clip(StrokeCache *cache, float *co, const float val[3])
{
int i;
-
for(i=0; i<3; ++i) {
- if(sd->flags & (SCULPT_LOCK_X << i))
- continue;
-
- if((sd->session->cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= sd->session->cache->clip_tolerance[i]))
+ if((cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= cache->clip_tolerance[i]))
co[i]= 0.0f;
else
co[i]= val[i];
}
}
+static void sculpt_axislock(Sculpt *sd, float *co)
+{
+ if(sd->flags == (SCULPT_LOCK_X|SCULPT_LOCK_Y|SCULPT_LOCK_Z))
+ return;
+
+ if(sd->session->cache->vc.v3d->twmode == V3D_MANIP_LOCAL) {
+ float mat[3][3], imat[3][3];
+ Mat3CpyMat4(mat, sd->session->cache->vc.obact->obmat);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(mat, co);
+ if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;
+ Mat3MulVecfl(imat, co);
+ } else {
+ if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;
+ }
+}
+
static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], const short no[3])
{
float fno[3] = {no[0], no[1], no[2]};
@@ -335,6 +353,8 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_
calc_area_normal(sd, area_normal, active_verts);
+ sculpt_axislock(sd, area_normal);
+
while(node){
float *co= ss->mvert[node->Index].co;
@@ -342,7 +362,7 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_
co[1]+area_normal[1]*ss->cache->radius*node->Fade*ss->cache->scale[1],
co[2]+area_normal[2]*ss->cache->radius*node->Fade*ss->cache->scale[2]};
- sculpt_clip(sd, co, val);
+ sculpt_clip(ss->cache, co, val);
node= node->next;
}
@@ -392,37 +412,37 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert)
VecCopyf(avg, ss->mvert[vert].co);
}
-static void do_smooth_brush(Sculpt *s, const ListBase* active_verts)
+static void do_smooth_brush(SculptSession *ss, const ListBase* active_verts)
{
ActiveData *node= active_verts->first;
int i;
for(i = 0; i < 2; ++i) {
while(node){
- float *co= s->session->mvert[node->Index].co;
+ float *co= ss->mvert[node->Index].co;
float avg[3], val[3];
- neighbor_average(s->session, avg, node->Index);
+ neighbor_average(ss, avg, node->Index);
val[0] = co[0]+(avg[0]-co[0])*node->Fade;
val[1] = co[1]+(avg[1]-co[1])*node->Fade;
val[2] = co[2]+(avg[2]-co[2])*node->Fade;
- sculpt_clip(s, co, val);
+ sculpt_clip(ss->cache, co, val);
node= node->next;
}
}
}
-static void do_pinch_brush(Sculpt *s, const ListBase* active_verts)
+static void do_pinch_brush(SculptSession *ss, const ListBase* active_verts)
{
ActiveData *node= active_verts->first;
while(node) {
- float *co= s->session->mvert[node->Index].co;
- const float val[3]= {co[0]+(s->session->cache->location[0]-co[0])*node->Fade,
- co[1]+(s->session->cache->location[1]-co[1])*node->Fade,
- co[2]+(s->session->cache->location[2]-co[2])*node->Fade};
- sculpt_clip(s, co, val);
+ float *co= ss->mvert[node->Index].co;
+ const float val[3]= {co[0]+(ss->cache->location[0]-co[0])*node->Fade,
+ co[1]+(ss->cache->location[1]-co[1])*node->Fade,
+ co[2]+(ss->cache->location[2]-co[2])*node->Fade};
+ sculpt_clip(ss->cache, co, val);
node= node->next;
}
}
@@ -434,6 +454,7 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss)
float grab_delta[3];
VecCopyf(grab_delta, ss->cache->grab_delta_symmetry);
+ sculpt_axislock(sd, grab_delta);
while(node) {
float *co= ss->mvert[node->Index].co;
@@ -441,7 +462,7 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss)
VecCopyf(add, grab_delta);
VecMulf(add, node->Fade);
VecAddf(add, add, co);
- sculpt_clip(sd, co, add);
+ sculpt_clip(ss->cache, co, add);
node= node->next;
}
@@ -452,38 +473,42 @@ static void do_layer_brush(Sculpt *sd, SculptSession *ss, const ListBase *active
{
float area_normal[3];
ActiveData *node= active_verts->first;
- float lim= ss->cache->radius / 4;
+ float lim= brush_strength(sd, ss->cache);
- if(ss->cache->flip)
+ if(sd->brush->flag & BRUSH_DIR_IN)
lim = -lim;
calc_area_normal(sd, area_normal, active_verts);
while(node){
float *disp= &ss->cache->layer_disps[node->Index];
- float *co= ss->mvert[node->Index].co;
- float val[3];
-
- *disp+= node->Fade;
-
- /* Don't let the displacement go past the limit */
- if((lim < 0 && *disp < lim) || (lim > 0 && *disp > lim))
- *disp = lim;
- val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0];
- val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1];
- val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2];
-
- sculpt_clip(sd, co, val);
+ if((lim > 0 && *disp < lim) ||
+ (lim < 0 && *disp > lim)) {
+ float *co= ss->mvert[node->Index].co;
+ float val[3];
+
+ *disp+= node->Fade;
+
+ if(lim < 0 && *disp < lim)
+ *disp = lim;
+ else if(lim > 0 && *disp > lim)
+ *disp = lim;
+
+ val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0];
+ val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1];
+ val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2];
+ //VecMulf(val, ss->cache->radius);
+ sculpt_clip(ss->cache, co, val);
+ }
node= node->next;
}
}
-static void do_inflate_brush(Sculpt *s, const ListBase *active_verts)
+static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts)
{
ActiveData *node= active_verts->first;
- SculptSession *ss = s->session;
float add[3];
while(node) {
@@ -499,7 +524,7 @@ static void do_inflate_brush(Sculpt *s, const ListBase *active_verts)
add[2]*= ss->cache->scale[2];
VecAddf(add, add, co);
- sculpt_clip(s, co, add);
+ sculpt_clip(ss->cache, co, add);
node= node->next;
}
@@ -562,7 +587,7 @@ static void do_flatten_clay_brush(Sculpt *sd, SculptSession *ss, const ListBase
VecAddf(val, val, tmp);
}
- sculpt_clip(sd, co, val);
+ sculpt_clip(ss->cache, co, val);
node= node->next;
}
@@ -738,6 +763,37 @@ static void sculpt_add_damaged_rect(SculptSession *ss)
}
}
+/* Clears the depth buffer in each modified area. */
+#if 0
+static void sculpt_clear_damaged_areas(SculptSession *ss)
+{
+ RectNode *rn= NULL;
+
+ for(rn = ss->damaged_rects.first; rn; rn = rn->next) {
+ rcti clp = rn->r;
+ rcti *win = NULL; /*XXX: &curarea->winrct; */
+
+ clp.xmin += win->xmin;
+ clp.xmax += win->xmin;
+ clp.ymin += win->ymin;
+ clp.ymax += win->ymin;
+
+ if(clp.xmin < win->xmax && clp.xmax > win->xmin &&
+ clp.ymin < win->ymax && clp.ymax > win->ymin) {
+ if(clp.xmin < win->xmin) clp.xmin = win->xmin;
+ if(clp.ymin < win->ymin) clp.ymin = win->ymin;
+ if(clp.xmax > win->xmax) clp.xmax = win->xmax;
+ if(clp.ymax > win->ymax) clp.ymax = win->ymax;
+
+ glScissor(clp.xmin + 1, clp.ymin + 1,
+ clp.xmax - clp.xmin - 2,
+ clp.ymax - clp.ymin - 2);
+ }
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+}
+#endif
static void do_brush_action(Sculpt *sd, StrokeCache *cache)
{
SculptSession *ss = sd->session;
@@ -789,13 +845,13 @@ static void do_brush_action(Sculpt *sd, StrokeCache *cache)
do_draw_brush(sd, ss, &active_verts);
break;
case SCULPT_TOOL_SMOOTH:
- do_smooth_brush(sd, &active_verts);
+ do_smooth_brush(ss, &active_verts);
break;
case SCULPT_TOOL_PINCH:
- do_pinch_brush(sd, &active_verts);
+ do_pinch_brush(ss, &active_verts);
break;
case SCULPT_TOOL_INFLATE:
- do_inflate_brush(sd, &active_verts);
+ do_inflate_brush(ss, &active_verts);
break;
case SCULPT_TOOL_GRAB:
do_grab_brush(sd, ss);
@@ -956,6 +1012,25 @@ static void sculpt_update_tex(Sculpt *sd)
}
}
+void sculptmode_selectbrush_menu(void)
+{
+ /* XXX: I guess menus belong elsewhere too?
+
+ Sculpt *sd= sculpt_data();
+ int val;
+
+ pupmenu_set_active(sd->brush_type);
+
+ val= pupmenu("Select Brush%t|Draw|Smooth|Pinch|Inflate|Grab|Layer|Flatten");
+
+ if(val>0) {
+ sd->brush_type= val;
+
+ allqueue(REDRAWVIEW3D, 1);
+ allqueue(REDRAWBUTSEDIT, 1);
+ }*/
+}
+
static void sculptmode_update_all_projverts(SculptSession *ss)
{
unsigned i;
@@ -1034,10 +1109,88 @@ static void sculpt_update_mesh_elements(bContext *C)
}
}
-static int sculpt_mode_poll(bContext *C)
+/* XXX: lots of drawing code (partial redraw), has to go elsewhere */
+#if 0
+void sculptmode_draw_wires(SculptSession *ss, int only_damaged)
+{
+ Mesh *me = get_mesh(OBACT);
+ int i;
+
+ bglPolygonOffset(1.0);
+ glDepthMask(0);
+ BIF_ThemeColor((OBACT==OBACT)?TH_ACTIVE:TH_SELECT);
+
+ for(i=0; i<me->totedge; i++) {
+ MEdge *med= &me->medge[i];
+
+ if((!only_damaged || (ss->projverts[med->v1].inside || ss->projverts[med->v2].inside)) &&
+ (med->flag & ME_EDGEDRAW)) {
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, &med->v1);
+ }
+ }
+
+ glDepthMask(1);
+ bglPolygonOffset(0.0);
+}
+
+void sculptmode_draw_mesh(int only_damaged)
{
- return G.f & G_SCULPTMODE;
+ int i, j, dt, drawCurrentMat = 1, matnr= -1;
+ SculptSession *ss = sculpt_session();
+
+ sculpt_update_mesh_elements(ss, OBACT);
+
+ persp(PERSP_VIEW);
+ mymultmatrix(OBACT->obmat);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ /* XXX: GPU_set_object_materials(G.scene, OBACT, 0, NULL); */
+ glEnable(GL_CULL_FACE);
+
+ glShadeModel(GL_SMOOTH);
+
+ glVertexPointer(3, GL_FLOAT, sizeof(MVert), &cache->mvert[0].co);
+ glNormalPointer(GL_SHORT, sizeof(MVert), &cache->mvert[0].no);
+
+ dt= MIN2(G.vd->drawtype, OBACT->dt);
+ if(dt==OB_WIRE)
+ glColorMask(0,0,0,0);
+
+ for(i=0; i<ss->totface; ++i) {
+ MFace *f= &ss->mface[i];
+ char inside= 0;
+ int new_matnr= f->mat_nr + 1;
+
+ if(new_matnr != matnr)
+ drawCurrentMat= GPU_enable_material(matnr = new_matnr, NULL);
+
+ /* If only_damaged!=0, only draw faces that are partially
+ inside the area(s) modified by the brush */
+ if(only_damaged) {
+ for(j=0; j<(f->v4?4:3); ++j) {
+ if(ss->projverts[*((&f->v1)+j)].inside) {
+ inside= 1;
+ break;
+ }
+ }
+ }
+ else
+ inside= 1;
+
+ if(inside && drawCurrentMat)
+ glDrawElements(f->v4?GL_QUADS:GL_TRIANGLES, f->v4?4:3, GL_UNSIGNED_INT, &f->v1);
+ }
+
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glColorMask(1,1,1,1);
+
+ if(dt==OB_WIRE || (OBACT->dtx & OB_DRAWWIRE))
+ sculptmode_draw_wires(ss, only_damaged);
+
+ glDisable(GL_DEPTH_TEST);
}
+#endif
static int sculpt_poll(bContext *C)
{
@@ -1116,7 +1269,7 @@ static void SCULPT_OT_brush_curve_preset(wmOperatorType *ot)
ot->idname= "SCULPT_OT_brush_curve_preset";
ot->exec= sculpt_brush_curve_preset_exec;
- ot->poll= sculpt_mode_poll;
+ ot->poll= sculpt_poll;
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -1181,8 +1334,6 @@ static void sculpt_cache_free(StrokeCache *cache)
MEM_freeN(cache->mesh_store);
if(cache->orig_norms)
MEM_freeN(cache->orig_norms);
- if(cache->face_norms)
- MEM_freeN(cache->face_norms);
if(cache->mats)
MEM_freeN(cache->mats);
MEM_freeN(cache);
@@ -1211,11 +1362,9 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *
sculpt_update_mesh_elements(C);
- if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER)
- cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements");
-
/* Make copies of the mesh vertex locations and normals for some tools */
if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER || (sd->brush->flag & BRUSH_ANCHORED)) {
+ cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements");
cache->mesh_store= MEM_mallocN(sizeof(float) * 3 * sd->session->totvert, "sculpt mesh vertices copy");
for(i = 0; i < sd->session->totvert; ++i)
VecCopyf(cache->mesh_store[i], sd->session->mvert[i].co);
@@ -1227,13 +1376,6 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *
cache->orig_norms[i][1] = sd->session->mvert[i].no[1];
cache->orig_norms[i][2] = sd->session->mvert[i].no[2];
}
-
- if(sd->session->face_normals) {
- float *fn = sd->session->face_normals;
- cache->face_norms= MEM_mallocN(sizeof(float) * 3 * sd->session->totface, "Sculpt face norms");
- for(i = 0; i < sd->session->totface; ++i, fn += 3)
- VecCopyf(cache->face_norms[i], fn);
- }
}
}
@@ -1343,6 +1485,9 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
view3d_operator_needs_opengl(C);
+ sculpt_brush_stroke_init_properties(C, op, event, sd->session);
+
+ sculptmode_update_all_projverts(sd->session);
/* TODO: Shouldn't really have to do this at the start of every
stroke, but sculpt would need some sort of notification when
@@ -1357,27 +1502,17 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
static void sculpt_restore_mesh(Sculpt *sd)
{
- SculptSession *ss = sd->session;
- StrokeCache *cache = ss->cache;
+ StrokeCache *cache = sd->session->cache;
int i;
/* Restore the mesh before continuing with anchored stroke */
if((sd->brush->flag & BRUSH_ANCHORED) && cache->mesh_store) {
- for(i = 0; i < ss->totvert; ++i) {
- VecCopyf(ss->mvert[i].co, cache->mesh_store[i]);
- ss->mvert[i].no[0] = cache->orig_norms[i][0];
- ss->mvert[i].no[1] = cache->orig_norms[i][1];
- ss->mvert[i].no[2] = cache->orig_norms[i][2];
- }
-
- if(ss->face_normals) {
- float *fn = ss->face_normals;
- for(i = 0; i < ss->totface; ++i, fn += 3)
- VecCopyf(fn, cache->face_norms[i]);
+ for(i = 0; i < sd->session->totvert; ++i) {
+ VecCopyf(sd->session->mvert[i].co, cache->mesh_store[i]);
+ sd->session->mvert[i].no[0] = cache->orig_norms[i][0];
+ sd->session->mvert[i].no[1] = cache->orig_norms[i][1];
+ sd->session->mvert[i].no[2] = cache->orig_norms[i][2];
}
-
- if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER)
- memset(cache->layer_disps, 0, sizeof(float) * ss->totvert);
}
}
@@ -1411,53 +1546,34 @@ static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event
{
PointerRNA itemptr;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- ARegion *ar = CTX_wm_region(C);
float center[3];
int mouse[2] = {event->x, event->y};
- float cur_depth;
sculpt_update_mesh_elements(C);
- if(!sd->session->cache) {
- ViewContext vc;
- view3d_set_viewcontext(C, &vc);
- cur_depth = read_cached_depth(&vc, event->x, event->y);
-
- /* Don't start the stroke until a valid depth is found */
- if(cur_depth < 1.0 - FLT_EPSILON) {
- sculpt_brush_stroke_init_properties(C, op, event, sd->session);
- sculptmode_update_all_projverts(sd->session);
- }
-
- ED_region_tag_redraw(ar);
- }
+ unproject(sd->session->cache->mats, center, event->x, event->y,
+ read_cached_depth(&sd->session->cache->vc, event->x, event->y));
- if(sd->session->cache) {
- cur_depth = read_cached_depth(&sd->session->cache->vc, event->x, event->y);
- unproject(sd->session->cache->mats, center, event->x, event->y, cur_depth);
+ /* Add to stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+ RNA_float_set_array(&itemptr, "location", center);
+ RNA_int_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "flip", event->shift);
+ sculpt_update_cache_variants(sd, &itemptr);
- /* Add to stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
- RNA_float_set_array(&itemptr, "location", center);
- RNA_int_set_array(&itemptr, "mouse", mouse);
- RNA_boolean_set(&itemptr, "flip", event->shift);
- sculpt_update_cache_variants(sd, &itemptr);
-
- sculpt_restore_mesh(sd);
- do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache);
+ sculpt_restore_mesh(sd);
+ do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache);
- sculpt_flush_update(C);
- sculpt_post_stroke_free(sd->session);
- }
+ sculpt_flush_update(C);
+ sculpt_post_stroke_free(sd->session);
/* Finished */
if(event->type == LEFTMOUSE && event->val == 0) {
- if(sd->session->cache) {
- request_depth_update(sd->session->cache->vc.rv3d);
- sculpt_cache_free(sd->session->cache);
- sd->session->cache = NULL;
- sculpt_undo_push(C, sd);
- }
+ request_depth_update(sd->session->cache->vc.rv3d);
+
+ sculpt_cache_free(sd->session->cache);
+
+ sculpt_undo_push(C, sd);
return OPERATOR_FINISHED;
}
@@ -1601,3 +1717,454 @@ void ED_operatortypes_sculpt()
WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
WM_operatortype_append(SCULPT_OT_brush_curve_preset);
}
+
+void sculpt(Sculpt *sd)
+{
+#if 0
+ SculptSession *ss= sd->session;
+ Object *ob= NULL; /*XXX */
+ Mesh *me;
+ MultiresModifierData *mmd = NULL;
+ /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */
+ short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut;
+ short modifier_calculations= 0;
+ BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action");
+ short spacing= 32000;
+ int scissor_box[4];
+ float offsetRot;
+ int smooth_stroke = 0, i;
+ int anchored, rake = 0 /* XXX: rake = ? */;
+
+ /* XXX: checking that sculpting is allowed
+ if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0))
+ return;
+ if(!(ob->lay & G.vd->lay))
+ error("Active object is not in this layer");
+ if(ob_get_keyblock(ob)) {
+ if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
+ error("Cannot sculpt on unlocked shape key");
+ return;
+ }
+ }*/
+
+ anchored = sd->brush->flag & BRUSH_ANCHORED;
+ smooth_stroke = (sd->flags & SCULPT_INPUT_SMOOTH) && (sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && !anchored;
+
+ if(smooth_stroke)
+ sculpt_stroke_new(256);
+
+ ss->damaged_rects.first = ss->damaged_rects.last = NULL;
+ ss->damaged_verts.first = ss->damaged_verts.last = NULL;
+ ss->vertexcosnos = NULL;
+
+ mmd = sculpt_multires_active(ob);
+
+ /* Check that vertex users are up-to-date */
+ if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != cache->totvert) {
+ sculpt_vertexusers_free(ss);
+ calc_vertex_users(ss);
+ if(ss->projverts)
+ MEM_freeN(ss->projverts);
+ ss->projverts = NULL;
+ active_ob= ob;
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ /*XXX:
+ persp(PERSP_VIEW);
+ getmouseco_areawin(mvalo);*/
+
+ /* Init texture
+ FIXME: Shouldn't be doing this every time! */
+ if(sd->tex_mode!=SCULPTREPT_3D)
+ sculptmode_update_tex(sd);
+
+ /*XXX: getmouseco_areawin(mouse); */
+ mvalo[0]= mouse[0];
+ mvalo[1]= mouse[1];
+ lastSigMouse[0]=mouse[0];
+ lastSigMouse[1]=mouse[1];
+ mousebut = 0; /* XXX: L_MOUSE; */
+
+ /* If modifier_calculations is true, then extra time must be spent
+ updating the mesh. This takes a *lot* longer, so it's worth
+ skipping if the modifier stack is empty. */
+ modifier_calculations= sculpt_modifiers_active(ob);
+
+ if(modifier_calculations)
+ ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /* XXX: scene = ? */
+ sculptmode_update_all_projverts(ss);
+
+ /* Capture original copy */
+ if(sd->flags & SCULPT_DRAW_FAST)
+ glAccum(GL_LOAD, 1);
+
+ /* Get original scissor box */
+ glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
+
+ /* For raking, get the original angle*/
+ offsetRot=sculpt_tex_angle(sd);
+
+ me = get_mesh(ob);
+
+ while (/*XXX:get_mbut() & mousebut*/0) {
+ /* XXX: getmouseco_areawin(mouse); */
+ /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */
+ if (rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){
+ /*Nasty looking, but just orig + new angle really*/
+ set_tex_angle(sd, offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0]))));
+ lastSigMouse[0]=mouse[0];
+ lastSigMouse[1]=mouse[1];
+ }
+
+ if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] ||
+ sd->brush->flag & BRUSH_AIRBRUSH) {
+ a->firsttime = firsttime;
+ firsttime= 0;
+
+ if(smooth_stroke)
+ sculpt_stroke_add_point(ss->stroke, mouse[0], mouse[1]);
+
+ spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2));
+
+ if(modifier_calculations && !ss->vertexcosnos)
+ ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /*XXX scene = ? */
+
+ if(sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
+ if(anchored) {
+ /* Restore the mesh before continuing with anchored stroke */
+ /*if(a->mesh_store) {
+ for(i = 0; i < cache->totvert; ++i) {
+ VecCopyf(cache->mvert[i].co, &a->mesh_store[i].x);
+ cache->mvert[i].no[0] = a->orig_norms[i][0];
+ cache->mvert[i].no[1] = a->orig_norms[i][1];
+ cache->mvert[i].no[2] = a->orig_norms[i][2];
+ }
+ }*/
+
+ //do_symmetrical_brush_actions(sd, a, mouse, NULL);
+ }
+ else {
+ if(smooth_stroke) {
+ sculpt_stroke_apply(sd, ss->stroke);
+ }
+ else if(sd->spacing==0 || spacing>sd->spacing) {
+ //do_symmetrical_brush_actions(sd, a, mouse, NULL);
+ spacing= 0;
+ }
+ }
+ }
+ else {
+ //do_symmetrical_brush_actions(sd, a, mouse, mvalo);
+ //unproject(ss, sd->pivot, mouse[0], mouse[1], a->depth);
+ }
+
+ if((!ss->multires && modifier_calculations) || ob_get_keyblock(ob)) {
+ /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); */ }
+
+ if(modifier_calculations || sd->brush->sculpt_tool == SCULPT_TOOL_GRAB || !(sd->flags & SCULPT_DRAW_FAST)) {
+ calc_damaged_verts(ss, a);
+ /*XXX: scrarea_do_windraw(curarea);
+ screen_swapbuffers(); */
+ } else { /* Optimized drawing */
+ calc_damaged_verts(ss, a);
+
+ /* Draw the stored image to the screen */
+ glAccum(GL_RETURN, 1);
+
+ sculpt_clear_damaged_areas(ss);
+
+ /* Draw all the polygons that are inside the modified area(s) */
+ glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
+ /* XXX: sculptmode_draw_mesh(1); */
+ glAccum(GL_LOAD, 1);
+
+ projverts_clear_inside(ss);
+
+ /* XXX: persp(PERSP_WIN); */
+ glDisable(GL_DEPTH_TEST);
+
+ /* Draw cursor */
+ if(sd->flags & SCULPT_TOOL_DRAW)
+ fdrawXORcirc((float)mouse[0],(float)mouse[1],sd->brush->size);
+ /* XXX: if(smooth_stroke)
+ sculpt_stroke_draw();
+
+ myswapbuffers(); */
+ }
+
+ BLI_freelistN(&ss->damaged_rects);
+ ss->damaged_rects.first = ss->damaged_rects.last = NULL;
+
+ mvalo[0]= mouse[0];
+ mvalo[1]= mouse[1];
+
+ if(ss->vertexcosnos) {
+ MEM_freeN(ss->vertexcosnos);
+ ss->vertexcosnos= NULL;
+ }
+
+ }
+ else { /*XXX:BIF_wait_for_statechange();*/ }
+ }
+
+ /* Set the rotation of the brush back to what it was before any rake */
+ set_tex_angle(sd, offsetRot);
+
+ if(smooth_stroke) {
+ sculpt_stroke_apply_all(sd, ss->stroke);
+ calc_damaged_verts(ss, a);
+ BLI_freelistN(&ss->damaged_rects);
+ }
+
+ //if(a->layer_disps) MEM_freeN(a->layer_disps);
+ //if(a->mesh_store) MEM_freeN(a->mesh_store);
+ //if(a->orig_norms) MEM_freeN(a->orig_norms);
+ for(i=0; i<8; ++i)
+ BLI_freelistN(&a->grab_active_verts[i]);
+ MEM_freeN(a);
+ sculpt_stroke_free(ss->stroke);
+ ss->stroke = NULL;
+
+ if(mmd) {
+ if(mmd->undo_verts && mmd->undo_verts != cache->mvert)
+ MEM_freeN(mmd->undo_verts);
+
+ mmd->undo_verts = cache->mvert;
+ mmd->undo_verts_tot = cache->totvert;
+ }
+
+ //sculpt_undo_push(sd);
+
+ /* XXX: if(G.vd->depths) G.vd->depths->damaged= 1;
+ allqueue(REDRAWVIEW3D, 0); */
+#endif
+}
+
+/* Partial Mesh Visibility */
+
+/* XXX: Partial vis. always was a mess, have to figure something out */
+#if 0
+/* mode: 0=hide outside selection, 1=hide inside selection */
+static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
+{
+ Mesh *me= get_mesh(ob);
+ float hidebox[6][3];
+ vec3f plane_normals[4];
+ float plane_ds[4];
+ unsigned i, j;
+ unsigned ndx_show, ndx_hide;
+ MVert *nve;
+ unsigned face_cnt_show= 0, face_ndx_show= 0;
+ unsigned edge_cnt_show= 0, edge_ndx_show= 0;
+ unsigned *old_map= NULL;
+ const unsigned SHOW= 0, HIDE=1;
+
+ /* Convert hide box from 2D to 3D */
+ unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1);
+ unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1);
+ unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1);
+ unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1);
+ unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0);
+ unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0);
+
+ /* Calculate normals for each side of hide box */
+ CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x);
+ CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x);
+ CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x);
+ CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x);
+
+ /* Calculate D for each side of hide box */
+ for(i= 0; i<4; ++i)
+ plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y +
+ hidebox[i][2]*plane_normals[i].z;
+
+ /* Add partial visibility to mesh */
+ if(!me->pv) {
+ me->pv= MEM_callocN(sizeof(PartialVisibility),"PartialVisibility");
+ } else {
+ old_map= MEM_callocN(sizeof(unsigned)*me->pv->totvert,"PMV oldmap");
+ for(i=0; i<me->pv->totvert; ++i) {
+ old_map[i]= me->pv->vert_map[i]<me->totvert?0:1;
+ }
+ mesh_pmv_revert(ob, me);
+ }
+
+ /* Kill sculpt data */
+ active_ob= NULL;
+
+ /* Initalize map with which verts are to be hidden */
+ me->pv->vert_map= MEM_mallocN(sizeof(unsigned)*me->totvert, "PMV vertmap");
+ me->pv->totvert= me->totvert;
+ me->totvert= 0;
+ for(i=0; i<me->pv->totvert; ++i) {
+ me->pv->vert_map[i]= mode ? HIDE:SHOW;
+ for(j=0; j<4; ++j) {
+ if(me->mvert[i].co[0] * plane_normals[j].x +
+ me->mvert[i].co[1] * plane_normals[j].y +
+ me->mvert[i].co[2] * plane_normals[j].z < plane_ds[j] ) {
+ me->pv->vert_map[i]= mode ? SHOW:HIDE; /* Vert is outside the hide box */
+ break;
+ }
+ }
+ if(old_map && old_map[i]) me->pv->vert_map[i]= 1;
+ if(!me->pv->vert_map[i]) ++me->totvert;
+
+ }
+ if(old_map) MEM_freeN(old_map);
+
+ /* Find out how many faces to show */
+ for(i=0; i<me->totface; ++i) {
+ if(!me->pv->vert_map[me->mface[i].v1] &&
+ !me->pv->vert_map[me->mface[i].v2] &&
+ !me->pv->vert_map[me->mface[i].v3]) {
+ if(me->mface[i].v4) {
+ if(!me->pv->vert_map[me->mface[i].v4])
+ ++face_cnt_show;
+ }
+ else ++face_cnt_show;
+ }
+ }
+ /* Find out how many edges to show */
+ for(i=0; i<me->totedge; ++i) {
+ if(!me->pv->vert_map[me->medge[i].v1] &&
+ !me->pv->vert_map[me->medge[i].v2])
+ ++edge_cnt_show;
+ }
+
+ /* Create new vert array and reset each vert's map with map[old]=new index */
+ nve= MEM_mallocN(sizeof(MVert)*me->pv->totvert, "PMV verts");
+ ndx_show= 0; ndx_hide= me->totvert;
+ for(i=0; i<me->pv->totvert; ++i) {
+ if(me->pv->vert_map[i]) {
+ me->pv->vert_map[i]= ndx_hide;
+ nve[me->pv->vert_map[i]]= me->mvert[i];
+ ++ndx_hide;
+ } else {
+ me->pv->vert_map[i]= ndx_show;
+ nve[me->pv->vert_map[i]]= me->mvert[i];
+ ++ndx_show;
+ }
+ }
+ CustomData_free_layer_active(&me->vdata, CD_MVERT, me->pv->totvert);
+ me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, nve, me->totvert);
+
+ /* Create new face array */
+ me->pv->old_faces= me->mface;
+ me->pv->totface= me->totface;
+ me->mface= MEM_mallocN(sizeof(MFace)*face_cnt_show, "PMV faces");
+ for(i=0; i<me->totface; ++i) {
+ MFace *pr_f= &me->pv->old_faces[i];
+ char show= 0;
+
+ if(me->pv->vert_map[pr_f->v1] < me->totvert &&
+ me->pv->vert_map[pr_f->v2] < me->totvert &&
+ me->pv->vert_map[pr_f->v3] < me->totvert) {
+ if(pr_f->v4) {
+ if(me->pv->vert_map[pr_f->v4] < me->totvert)
+ show= 1;
+ }
+ else show= 1;
+ }
+
+ if(show) {
+ MFace *cr_f= &me->mface[face_ndx_show];
+ *cr_f= *pr_f;
+ cr_f->v1= me->pv->vert_map[pr_f->v1];
+ cr_f->v2= me->pv->vert_map[pr_f->v2];
+ cr_f->v3= me->pv->vert_map[pr_f->v3];
+ cr_f->v4= pr_f->v4 ? me->pv->vert_map[pr_f->v4] : 0;
+ test_index_face(cr_f,NULL,0,pr_f->v4?4:3);
+ ++face_ndx_show;
+ }
+ }
+ me->totface= face_cnt_show;
+ CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
+
+ /* Create new edge array */
+ me->pv->old_edges= me->medge;
+ me->pv->totedge= me->totedge;
+ me->medge= MEM_mallocN(sizeof(MEdge)*edge_cnt_show, "PMV edges");
+ me->pv->edge_map= MEM_mallocN(sizeof(int)*me->pv->totedge,"PMV edgemap");
+ for(i=0; i<me->totedge; ++i) {
+ if(me->pv->vert_map[me->pv->old_edges[i].v1] < me->totvert &&
+ me->pv->vert_map[me->pv->old_edges[i].v2] < me->totvert) {
+ MEdge *cr_e= &me->medge[edge_ndx_show];
+ me->pv->edge_map[i]= edge_ndx_show;
+ *cr_e= me->pv->old_edges[i];
+ cr_e->v1= me->pv->vert_map[me->pv->old_edges[i].v1];
+ cr_e->v2= me->pv->vert_map[me->pv->old_edges[i].v2];
+ ++edge_ndx_show;
+ }
+ else me->pv->edge_map[i]= -1;
+ }
+ me->totedge= edge_cnt_show;
+ CustomData_set_layer(&me->edata, CD_MEDGE, me->medge);
+
+ /* XXX: DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); */
+}
+
+static rcti sculptmode_pmv_box()
+{
+ /*XXX: short down[2], mouse[2];
+ rcti ret;
+
+ getmouseco_areawin(down);
+
+ while((get_mbut()&L_MOUSE) || (get_mbut()&R_MOUSE)) {
+ getmouseco_areawin(mouse);
+
+ scrarea_do_windraw(curarea);
+
+ persp(PERSP_WIN);
+ glLineWidth(2);
+ setlinestyle(2);
+ sdrawXORline(down[0],down[1],mouse[0],down[1]);
+ sdrawXORline(mouse[0],down[1],mouse[0],mouse[1]);
+ sdrawXORline(mouse[0],mouse[1],down[0],mouse[1]);
+ sdrawXORline(down[0],mouse[1],down[0],down[1]);
+ setlinestyle(0);
+ glLineWidth(1);
+ persp(PERSP_VIEW);
+
+ screen_swapbuffers();
+ backdrawview3d(0);
+ }
+
+ ret.xmin= down[0]<mouse[0]?down[0]:mouse[0];
+ ret.ymin= down[1]<mouse[1]?down[1]:mouse[1];
+ ret.xmax= down[0]>mouse[0]?down[0]:mouse[0];
+ ret.ymax= down[1]>mouse[1]?down[1]:mouse[1];
+ return ret;*/
+}
+
+void sculptmode_pmv(int mode)
+{
+ Object *ob= NULL; /*XXX: OBACT; */
+ rcti hb_2d;
+
+ if(ob_get_key(ob)) {
+ error("Cannot hide mesh with shape keys enabled");
+ return;
+ }
+
+ hb_2d= sculptmode_pmv_box(); /* Get 2D hide box */
+
+ sculptmode_correct_state();
+
+ waitcursor(1);
+
+ if(hb_2d.xmax-hb_2d.xmin > 3 && hb_2d.ymax-hb_2d.ymin > 3) {
+ init_sculptmatrices();
+
+ sculptmode_do_pmv(ob,&hb_2d,mode);
+ }
+ else mesh_pmv_off(ob, get_mesh(ob));
+
+ /*XXX: scrarea_do_windraw(curarea); */
+
+ waitcursor(0);
+}
+#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index febca301939..112da5b4f0f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BDR_sculptmode.h 13396 2008-01-25 04:17:38Z nicholasbishop $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/sculpt_paint/sculpt_stroke.c b/source/blender/editors/sculpt_paint/sculpt_stroke.c
index 554ff580358..1c23ec2a546 100644
--- a/source/blender/editors/sculpt_paint/sculpt_stroke.c
+++ b/source/blender/editors/sculpt_paint/sculpt_stroke.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: sculpt_stroke.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_action/Makefile b/source/blender/editors/space_action/Makefile
index e856587acca..840f31b8a40 100644
--- a/source/blender/editors/space_action/Makefile
+++ b/source/blender/editors/space_action/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 2c9f91e0941..6eae581aa40 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 5d262cb03c5..a0f1adbd97e 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 06f35f5cf05..b82e44f3aa3 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_api/Makefile b/source/blender/editors/space_api/Makefile
index 474fbe89053..46f926afbc9 100644
--- a/source/blender/editors/space_api/Makefile
+++ b/source/blender/editors/space_api/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 510103895f4..4f9c1f4b7a7 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -50,7 +50,6 @@
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_uvedit.h"
-#include "ED_pointcache.h"
/* only call once on startup, storage is global in BKE kernel listbase */
void ED_spacetypes_init(void)
@@ -90,7 +89,6 @@ void ED_spacetypes_init(void)
ED_operatortypes_curve();
ED_operatortypes_armature();
ED_marker_operatortypes();
- ED_operatortypes_pointcache();
ui_view2d_operatortypes();
diff --git a/source/blender/editors/space_buttons/Makefile b/source/blender/editors/space_buttons/Makefile
index a4894ede06b..b96d1cc5495 100644
--- a/source/blender/editors/space_buttons/Makefile
+++ b/source/blender/editors/space_buttons/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index a0a7dad4077..541da52f7f9 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -12,4 +12,7 @@ defs = []
if env['WITH_BF_GAMEENGINE']:
defs.append('GAMEBLENDER=1')
+ if env['WITH_BF_SOLID']:
+ defs.append('USE_SUMO_SOLID')
+
env.BlenderLib ( 'bf_editors_space_buttons', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 01794d1bba8..d97b4acdb96 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -552,7 +552,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if(ptr) {
Object *ob= ptr->data;
- if(ob && ob->type && (ob->type<OB_LAMP) && ob->totcol)
+ if(ob && ob->type && (ob->type<OB_LAMP))
CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
}
@@ -668,6 +668,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
uiBlock *block;
uiBut *but;
PointerRNA *ptr;
+ PropertyRNA *nameprop;
char namebuf[128], *name;
int a, icon;
@@ -687,7 +688,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
if(ptr->data) {
icon= RNA_struct_ui_icon(ptr->type);
- name= RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf));
+ nameprop= RNA_struct_name_property(ptr->type);
#if 0
if(sbuts->mainb != BCONTEXT_SCENE && ptr->type == &RNA_Scene) {
@@ -695,7 +696,9 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
}
else
#endif
- if(name) {
+ if(nameprop) {
+ name= RNA_property_string_get_alloc(ptr, nameprop, namebuf, sizeof(namebuf));
+
uiItemL(row, name, icon);
if(name != namebuf)
diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c
index 7c622f172a2..98fd198d84b 100644
--- a/source/blender/editors/space_buttons/buttons_header.c
+++ b/source/blender/editors/space_buttons/buttons_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: buttons_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -173,10 +173,10 @@ void buttons_header_buttons(const bContext *C, ARegion *ar)
uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT_DATA, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_OBJECT, 0, 0, "Object");
if(sbuts->pathflag & (1<<BCONTEXT_CONSTRAINT))
uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_CONSTRAINT, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_CONSTRAINT, 0, 0, "Constraint");
- if(sbuts->pathflag & (1<<BCONTEXT_DATA))
- uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, sbuts->dataicon, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_DATA, 0, 0, "Object Data");
if(sbuts->pathflag & (1<<BCONTEXT_MODIFIER))
uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_MODIFIER, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_MODIFIER, 0, 0, "Modifier");
+ if(sbuts->pathflag & (1<<BCONTEXT_DATA))
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, sbuts->dataicon, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_DATA, 0, 0, "Object Data");
if(sbuts->pathflag & (1<<BCONTEXT_BONE))
uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_BONE_DATA, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_BONE, 0, 0, "Bone");
if(sbuts->pathflag & (1<<BCONTEXT_MATERIAL))
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 13ea778fb00..196647a3750 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -61,20 +61,9 @@ void buttons_context_draw(const struct bContext *C, struct uiLayout *layout);
void buttons_context_register(struct ARegionType *art);
/* buttons_ops.c */
-void OBJECT_OT_material_slot_add(struct wmOperatorType *ot);
-void OBJECT_OT_material_slot_remove(struct wmOperatorType *ot);
-void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot);
-void OBJECT_OT_material_slot_select(struct wmOperatorType *ot);
-void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot);
-
void MATERIAL_OT_new(struct wmOperatorType *ot);
void TEXTURE_OT_new(struct wmOperatorType *ot);
void WORLD_OT_new(struct wmOperatorType *ot);
-void OBJECT_OT_particle_system_slot_add(struct wmOperatorType *ot);
-void OBJECT_OT_particle_system_slot_remove(struct wmOperatorType *ot);
-
-void PARTICLE_OT_new(struct wmOperatorType *ot);
-
#endif /* ED_BUTTONS_INTERN_H */
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 6ca92674c6e..63469a8294d 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -30,7 +30,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
@@ -38,251 +37,31 @@
#include "DNA_world_types.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_font.h"
#include "BKE_library.h"
#include "BKE_material.h"
-#include "BKE_particle.h"
#include "BKE_texture.h"
-#include "BKE_utildefines.h"
#include "BKE_world.h"
-#include "BLI_editVert.h"
-
#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_curve.h"
-#include "ED_mesh.h"
-
#include "buttons_intern.h" // own include
-/********************** material slot operators *********************/
-
-static int material_slot_add_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
-
- if(!ob)
- return OPERATOR_CANCELLED;
-
- object_add_material_slot(ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_material_slot_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Material Slot";
- ot->idname= "OBJECT_OT_material_slot_add";
-
- /* api callbacks */
- ot->exec= material_slot_add_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int material_slot_remove_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
-
- if(!ob)
- return OPERATOR_CANCELLED;
-
- object_remove_material_slot(ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Remove Material Slot";
- ot->idname= "OBJECT_OT_material_slot_remove";
-
- /* api callbacks */
- ot->exec= material_slot_remove_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int material_slot_assign_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
-
- if(!ob)
- return OPERATOR_CANCELLED;
-
- if(ob && ob->actcol>0) {
- if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
- EditFace *efa;
-
- if(em) {
- for(efa= em->faces.first; efa; efa=efa->next)
- if(efa->f & SELECT)
- efa->mat_nr= ob->actcol-1;
- }
- }
- else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ListBase *editnurb= ((Curve*)ob->data)->editnurb;
- Nurb *nu;
-
- if(editnurb) {
- for(nu= editnurb->first; nu; nu= nu->next)
- if(isNurbsel(nu))
- nu->mat_nr= nu->charidx= ob->actcol-1;
- }
- }
- else if(ob->type == OB_FONT) {
- EditFont *ef= ((Curve*)ob->data)->editfont;
- int i, selstart, selend;
-
- if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
- for(i=selstart; i<=selend; i++)
- ef->textbufinfo[i].mat_nr = ob->actcol-1;
- }
- }
- }
-
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Assign Material Slot";
- ot->idname= "OBJECT_OT_material_slot_assign";
-
- /* api callbacks */
- ot->exec= material_slot_assign_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int material_slot_de_select(bContext *C, int select)
-{
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
-
- if(!ob)
- return OPERATOR_CANCELLED;
-
- if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
-
- if(em) {
- if(select)
- EM_select_by_material(em, ob->actcol-1);
- else
- EM_deselect_by_material(em, ob->actcol-1);
- }
- }
- else if ELEM(ob->type, OB_CURVE, OB_SURF) {
- ListBase *editnurb= ((Curve*)ob->data)->editnurb;
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
- for(nu= editnurb->first; nu; nu=nu->next) {
- if(nu->mat_nr==ob->actcol-1) {
- if(nu->bezt) {
- a= nu->pntsu;
- bezt= nu->bezt;
- while(a--) {
- if(bezt->hide==0) {
- if(select) {
- bezt->f1 |= SELECT;
- bezt->f2 |= SELECT;
- bezt->f3 |= SELECT;
- }
- else {
- bezt->f1 &= ~SELECT;
- bezt->f2 &= ~SELECT;
- bezt->f3 &= ~SELECT;
- }
- }
- bezt++;
- }
- }
- else if(nu->bp) {
- a= nu->pntsu*nu->pntsv;
- bp= nu->bp;
- while(a--) {
- if(bp->hide==0) {
- if(select) bp->f1 |= SELECT;
- else bp->f1 &= ~SELECT;
- }
- bp++;
- }
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static int material_slot_select_exec(bContext *C, wmOperator *op)
-{
- return material_slot_de_select(C, 1);
-}
-
-void OBJECT_OT_material_slot_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Material Slot";
- ot->idname= "OBJECT_OT_material_slot_select";
-
- /* api callbacks */
- ot->exec= material_slot_select_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int material_slot_deselect_exec(bContext *C, wmOperator *op)
-{
- return material_slot_de_select(C, 0);
-}
-
-void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Deselect Material Slot";
- ot->idname= "OBJECT_OT_material_slot_deselect";
-
- /* api callbacks */
- ot->exec= material_slot_deselect_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
/********************** new material operator *********************/
static int new_material_exec(bContext *C, wmOperator *op)
{
- Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- Object *ob;
PointerRNA ptr;
+ Material *ma;
+ Object *ob;
int index;
/* add or copy material */
+ ptr= CTX_data_pointer_get(C, "material");
+ ma= (RNA_struct_is_a(ptr.type, &RNA_Material))? ptr.data: NULL;
+
if(ma)
ma= copy_material(ma);
else
@@ -291,9 +70,9 @@ static int new_material_exec(bContext *C, wmOperator *op)
ma->id.us--; /* compensating for us++ in assign_material */
/* attempt to assign to material slot */
- ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
+ ptr= CTX_data_pointer_get(C, "material_slot");
- if(ptr.data) {
+ if(RNA_struct_is_a(ptr.type, &RNA_MaterialSlot)) {
ob= ptr.id.data;
index= (Material**)ptr.data - ob->mat;
@@ -301,8 +80,6 @@ static int new_material_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
}
-
- WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
return OPERATOR_FINISHED;
}
@@ -324,12 +101,15 @@ void MATERIAL_OT_new(wmOperatorType *ot)
static int new_texture_exec(bContext *C, wmOperator *op)
{
- Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ PointerRNA ptr;
ID *id;
+ Tex *tex;
MTex *mtex;
- PointerRNA ptr;
/* add or copy texture */
+ ptr= CTX_data_pointer_get(C, "texture");
+ tex= (RNA_struct_is_a(ptr.type, &RNA_Texture))? ptr.data: NULL;
+
if(tex)
tex= copy_texture(tex);
else
@@ -338,9 +118,9 @@ static int new_texture_exec(bContext *C, wmOperator *op)
id_us_min(&tex->id);
/* attempt to assign to texture slot */
- ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
+ ptr= CTX_data_pointer_get(C, "texture_slot");
- if(ptr.data) {
+ if(RNA_struct_is_a(ptr.type, &RNA_TextureSlot)) {
id= ptr.id.data;
mtex= ptr.data;
@@ -353,8 +133,6 @@ static int new_texture_exec(bContext *C, wmOperator *op)
/* XXX nodes, notifier .. */
}
-
- WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
return OPERATOR_FINISHED;
}
@@ -376,21 +154,27 @@ void TEXTURE_OT_new(wmOperatorType *ot)
static int new_world_exec(bContext *C, wmOperator *op)
{
- Scene *scene= CTX_data_scene(C);
- World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+ PointerRNA ptr;
+ Scene *scene;
+ World *wo;
/* add or copy world */
+ ptr= CTX_data_pointer_get(C, "world");
+ wo= (RNA_struct_is_a(ptr.type, &RNA_World))? ptr.data: NULL;
+
if(wo)
wo= copy_world(wo);
else
wo= add_world("World");
/* assign to scene */
+ scene= CTX_data_scene(C);
+
if(scene->world)
id_us_min(&scene->world->id);
scene->world= wo;
- WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
+ // XXX notifier
return OPERATOR_FINISHED;
}
@@ -408,109 +192,3 @@ void WORLD_OT_new(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-
-
-/********************** particle system slot operators *********************/
-
-static int particle_system_slot_add_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- Scene *scene = CTX_data_scene(C);
-
- if(!scene || !ob)
- return OPERATOR_CANCELLED;
-
- object_add_particle_system_slot(scene, ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_particle_system_slot_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Particle System Slot";
- ot->idname= "OBJECT_OT_particle_system_slot_add";
-
- /* api callbacks */
- ot->exec= particle_system_slot_add_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int particle_system_slot_remove_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- Scene *scene = CTX_data_scene(C);
-
- if(!scene || !ob)
- return OPERATOR_CANCELLED;
-
- object_remove_particle_system_slot(scene, ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_particle_system_slot_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Remove Particle System Slot";
- ot->idname= "OBJECT_OT_particle_system_slot_remove";
-
- /* api callbacks */
- ot->exec= particle_system_slot_remove_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** new particle settings operator *********************/
-
-static int new_particle_settings_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ParticleSettings *part= CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings).data;
- Object *ob;
- PointerRNA ptr;
-
- /* add or copy particle setting */
- if(part)
- part= psys_copy_settings(part);
- else
- part= psys_new_settings("PSys", NULL);
-
- /* attempt to assign to material slot */
- ptr= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
-
- if(ptr.data) {
- ParticleSystem *psys = (ParticleSystem*)ptr.data;
- ob= ptr.id.data;
-
- if(psys->part)
- psys->part->id.us--;
-
- psys->part = part;
-
- DAG_scene_sort(scene);
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "New Particle Settings";
- ot->idname= "PARTICLE_OT_new";
-
- /* api callbacks */
- ot->exec= new_particle_settings_exec;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 7954d5254cc..38ce88019ed 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -210,20 +210,9 @@ static void buttons_main_area_draw(const bContext *C, ARegion *ar)
void buttons_operatortypes(void)
{
- WM_operatortype_append(OBJECT_OT_material_slot_add);
- WM_operatortype_append(OBJECT_OT_material_slot_remove);
- WM_operatortype_append(OBJECT_OT_material_slot_assign);
- WM_operatortype_append(OBJECT_OT_material_slot_select);
- WM_operatortype_append(OBJECT_OT_material_slot_deselect);
-
WM_operatortype_append(MATERIAL_OT_new);
WM_operatortype_append(TEXTURE_OT_new);
WM_operatortype_append(WORLD_OT_new);
-
- WM_operatortype_append(OBJECT_OT_particle_system_slot_add);
- WM_operatortype_append(OBJECT_OT_particle_system_slot_remove);
-
- WM_operatortype_append(PARTICLE_OT_new);
}
void buttons_keymap(struct wmWindowManager *wm)
@@ -231,23 +220,14 @@ void buttons_keymap(struct wmWindowManager *wm)
}
-//#define PY_HEADER
/* add handlers, stuff you only do once or on area/region changes */
static void buttons_header_area_init(wmWindowManager *wm, ARegion *ar)
{
-#ifdef PY_HEADER
- ED_region_header_init(ar);
-#else
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
-#endif
}
static void buttons_header_area_draw(const bContext *C, ARegion *ar)
{
-#ifdef PY_HEADER
- ED_region_header(C, ar);
-#else
-
float col[3];
/* clear */
@@ -263,8 +243,7 @@ static void buttons_header_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(C, &ar->v2d);
buttons_header_buttons(C, ar);
-#endif
-
+
/* restore view matrix? */
UI_view2d_view_restore(C);
}
@@ -348,11 +327,6 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
case ND_GEOM_SELECT:
ED_area_tag_redraw(sa);
break;
- case ND_SHADING:
- case ND_SHADING_DRAW:
- /* currently works by redraws... if preview is set, it (re)starts job */
- sbuts->preview= 1;
- break;
}
break;
case NC_MATERIAL:
@@ -363,6 +337,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
case ND_SHADING_DRAW:
/* currently works by redraws... if preview is set, it (re)starts job */
sbuts->preview= 1;
+ printf("shader notifier \n");
break;
}
break;
diff --git a/source/blender/editors/space_file/Makefile b/source/blender/editors/space_file/Makefile
index 2f4180448e5..8f48217473c 100644
--- a/source/blender/editors/space_file/Makefile
+++ b/source/blender/editors/space_file/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index bb47d3458fe..6ed8f87d987 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -550,24 +550,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
}
-static void file_draw_fsmenu_category_name(ARegion *ar, const char *category_name, short *starty)
-{
- short sx, sy;
- int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4;
- int fontsize = file_font_pointsize();
-
- sx = ar->v2d.cur.xmin + TILE_BORDER_X;
- sy = *starty;
-
- UI_ThemeColor(TH_TEXT_HI);
- file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END);
-
- sy -= fontsize*2.0f;
-
- *starty= sy;
-}
-
-static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, short *starty)
+static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, const char* category_name, short *starty)
{
struct FSMenu* fsmenu = fsmenu_get();
char bookmark[FILE_MAX];
@@ -582,6 +565,11 @@ static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCate
sx = ar->v2d.cur.xmin + TILE_BORDER_X;
sy = *starty;
+ UI_ThemeColor(TH_TEXT_HI);
+ file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END);
+
+ sy -= fontsize*2.0f;
+
switch(category) {
case FS_CATEGORY_SYSTEM:
cat_icon = ICON_DISK_DRIVE; break;
@@ -628,54 +616,15 @@ static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCate
*starty = sy;
}
-void file_draw_fsmenu_operator(const bContext *C, ARegion *ar, wmOperator *op, short *starty)
-{
- uiStyle *style= U.uistyles.first;
- uiBlock *block;
- uiLayout *layout;
- int sy;
-
- sy= *starty;
-
- block= uiBeginBlock(C, ar, "file_options", UI_EMBOSS);
- layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, TILE_BORDER_X, sy, ar->winx-2*TILE_BORDER_X, 20, style);
-
- RNA_STRUCT_BEGIN(op->ptr, prop) {
- if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
- continue;
- if(strcmp(RNA_property_identifier(prop), "filename") == 0)
- continue;
-
- uiItemFullR(layout, NULL, 0, op->ptr, prop, -1, 0, 0, 0, 0);
- }
- RNA_STRUCT_END;
-
- uiBlockLayoutResolve(C, block, NULL, &sy);
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
-
- *starty= sy;
-}
-
void file_draw_fsmenu(const bContext *C, ARegion *ar)
{
- SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
int linestep = file_font_pointsize()*2.0f;
short sy= ar->v2d.cur.ymax-2*TILE_BORDER_Y;
- file_draw_fsmenu_category_name(ar, "SYSTEM", &sy);
- file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, &sy);
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, "SYSTEM", &sy);
sy -= linestep;
- file_draw_fsmenu_category_name(ar, "BOOKMARKS", &sy);
- file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, &sy);
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, "BOOKMARKS", &sy);
sy -= linestep;
- file_draw_fsmenu_category_name(ar, "RECENT", &sy);
- file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, &sy);
-
- if(sfile->op) {
- sy -= linestep;
- file_draw_fsmenu_category_name(ar, "OPTIONS", &sy);
- file_draw_fsmenu_operator(C, ar, sfile->op, &sy);
- }
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, "RECENT", &sy);
+
}
-
diff --git a/source/blender/editors/space_file/file_header.c b/source/blender/editors/space_file/file_header.c
index 4799003d6c7..34374268d5c 100644
--- a/source/blender/editors/space_file/file_header.c
+++ b/source/blender/editors/space_file/file_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: file_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index ab02147d020..0c6cadc05c1 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -190,7 +190,7 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
rect.xmax= RNA_int_get(op->ptr, "xmax");
rect.ymax= RNA_int_get(op->ptr, "ymax");
- BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
+ BLI_isect_rctf(&(ar->v2d.mask), &rect, &rect);
file_select(sfile, ar, &rect, val );
WM_event_add_notifier(C, NC_WINDOW, NULL);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 479d9cabc55..d57fc7f90bc 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -159,7 +159,7 @@ float file_string_width(const char* str)
{
uiStyle *style= U.uistyles.first;
uiStyleFontSet(&style->widget);
- return BLF_width((char *)str);
+ return BLF_width(str);
}
float file_font_pointsize()
diff --git a/source/blender/editors/space_graph/Makefile b/source/blender/editors/space_graph/Makefile
index e04a354fb1d..340495ecc79 100644
--- a/source/blender/editors/space_graph/Makefile
+++ b/source/blender/editors/space_graph/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index ddf4105fdf4..acf712d0147 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: drawipo.c 17512 2008-11-20 05:55:42Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index b624d02a633..49397ed0edd 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 7746f49d135..9aaef9fca8a 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_image/Makefile b/source/blender/editors/space_image/Makefile
index e7e9a9b5665..44d841a0606 100644
--- a/source/blender/editors/space_image/Makefile
+++ b/source/blender/editors/space_image/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index a08a23c1263..b5df0257e71 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -383,7 +383,6 @@ static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block
}
}
-#if 0
static void image_panel_view_properties(const bContext *C, Panel *pa)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
@@ -440,7 +439,6 @@ static void image_panel_view_properties(const bContext *C, Panel *pa)
}
image_editcursor_buts(C, &ar->v2d, block);
}
-#endif
void brush_buttons(const bContext *C, uiBlock *block, short fromsima,
int evt_nop, int evt_change,
@@ -1025,53 +1023,42 @@ static void image_load_fs_cb(bContext *C, void *ima_pp_v, void *iuser_v)
static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v)
{
BKE_image_multilayer_index(rr_v, iuser_v);
- WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
}
static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v)
{
RenderResult *rr= rr_v;
ImageUser *iuser= iuser_v;
int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0); /* fake compo result layer */
-
- if(iuser->layer<tot-1) {
+ if(iuser->layer<tot-1)
iuser->layer++;
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
- }
+ BKE_image_multilayer_index(rr, iuser);
}
static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v)
{
ImageUser *iuser= iuser_v;
-
- if(iuser->layer>0) {
+ if(iuser->layer>0)
iuser->layer--;
- BKE_image_multilayer_index(rr_v, iuser);
- WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
- }
+ BKE_image_multilayer_index(rr_v, iuser);
}
static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
{
RenderResult *rr= rr_v;
ImageUser *iuser= iuser_v;
RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
-
if(rl) {
int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0); /* builtin render result has no combined pass in list */
if(iuser->pass<tot-1) {
iuser->pass++;
BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
}
}
}
static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
{
ImageUser *iuser= iuser_v;
-
if(iuser->pass>0) {
iuser->pass--;
BKE_image_multilayer_index(rr_v, iuser);
- WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
}
}
@@ -1366,23 +1353,6 @@ void ED_image_uiblock_panel(const bContext *C, uiBlock *block, Image **ima_pp, I
uiBlockEndAlign(block);
}
-void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
-{
- uiBlock *block= uiLayoutFreeBlock(layout);
- Scene *scene= CTX_data_scene(C);
- RenderResult *rr;
-
- /* render layers and passes */
- if(ima && iuser) {
- rr= BKE_image_get_renderresult(scene, ima);
-
- if(rr) {
- uiBlockBeginAlign(block);
- uiblock_layer_pass_buttons(block, rr, iuser, 0, 0, 0, 160);
- uiBlockEndAlign(block);
- }
- }
-}
static void image_panel_properties(const bContext *C, Panel *pa)
{
@@ -1407,6 +1377,12 @@ void image_buttons_register(ARegionType *art)
pt->draw= image_panel_properties;
BLI_addtail(&art->paneltypes, pt);
+ pt= MEM_callocN(sizeof(PanelType), "spacetype image view properties");
+ strcpy(pt->idname, "IMAGE_PT_view_properties");
+ strcpy(pt->label, "View Properties");
+ pt->draw= image_panel_view_properties;
+ BLI_addtail(&art->paneltypes, pt);
+
pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint");
strcpy(pt->idname, "IMAGE_PT_paint");
strcpy(pt->label, "Paint");
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index e61931f2fad..122e298baaa 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -311,14 +311,12 @@ static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, fl
// glColorMask(1, 1, 1, 1);
}
-#ifdef WITH_LCMS
static void sima_draw_colorcorrected_pixels(float x1, float y1, ImBuf *ibuf)
{
colorcorrection_do_ibuf(ibuf, "MONOSCNR.ICM"); /* path is hardcoded here, find some place better */
glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->crect);
}
-#endif
static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
{
@@ -452,7 +450,7 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty,
return rectmain;
}
-static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
+static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
{
unsigned int *rect;
int dx, dy, sx, sy, x, y;
@@ -479,7 +477,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, I
/* draw repeated */
for(sy=0; sy+dy<=ibuf->y; sy+= dy) {
for(sx=0; sx+dx<=ibuf->x; sx+= dx) {
- UI_view2d_to_region_no_clip(&ar->v2d, fx + (float)sx/(float)ibuf->x, fy + (float)sy/(float)ibuf->y, &x, &y);
+ UI_view2d_view_to_region(&ar->v2d, (float)sx/(float)ibuf->x, (float)sy/(float)ibuf->y, &x, &y);
glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
@@ -490,19 +488,16 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, I
MEM_freeN(rect);
}
-static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float zoomx, float zoomy)
{
float x, y;
double time_current;
time_current = PIL_check_seconds_timer();
- for(x=floor(ar->v2d.cur.xmin); x<ar->v2d.cur.xmax; x += 1.0f) {
- for(y=floor(ar->v2d.cur.ymin); y<ar->v2d.cur.ymax; y += 1.0f) {
- if(ima && (ima->tpageflag & IMA_TILES))
- draw_image_buffer_tiled(sima, ar, ima, ibuf, x, y, zoomx, zoomy);
- else
- draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy);
+ for(x=ar->v2d.cur.xmin; x<ar->v2d.cur.xmax; x += zoomx) {
+ for(y=ar->v2d.cur.ymin; y<ar->v2d.cur.ymax; y += zoomy) {
+ draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy);
/* only draw until running out of time */
if((PIL_check_seconds_timer() - time_current) > 0.25)
@@ -672,9 +667,9 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
if(ibuf==NULL)
draw_image_grid(ar, zoomx, zoomy);
else if(sima->flag & SI_DRAW_TILE)
- draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy);
+ draw_image_buffer_repeated(sima, ar, scene, ibuf, zoomx, zoomy);
else if(ima && (ima->tpageflag & IMA_TILES))
- draw_image_buffer_tiled(sima, ar, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
+ draw_image_buffer_tiled(sima, ar, ima, ibuf, zoomx, zoomy);
else
draw_image_buffer(sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
@@ -704,5 +699,12 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
}
}
#endif
+
+#if 0
+ /* it is important to end a view in a transform compatible with buttons */
+ bwin_scalematrix(sa->win, sima->blockscale, sima->blockscale, sima->blockscale);
+ if(!(G.rendering && show_render))
+ image_blockhandlers(sa);
+#endif
}
diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c
index 9550c4c3a29..adf4772efde 100644
--- a/source/blender/editors/space_image/image_header.c
+++ b/source/blender/editors/space_image/image_header.c
@@ -802,11 +802,11 @@ void image_header_buttons(const bContext *C, ARegion *ar)
uiBlockBeginAlign(block);
uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
- xco,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
+ xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
- xco+=XIC,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
- xco+=XIC,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
uiBlockEndAlign(block);
}
@@ -837,14 +837,14 @@ void image_header_buttons(const bContext *C, ARegion *ar)
/* snap options, identical to options in 3d view header */
uiBlockBeginAlign(block);
- if (scene->toolsettings->snap_flag & SCE_SNAP) {
- uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
xco+= XIC;
- uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->toolsettings->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
+ uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
xco+= 70;
}
else {
- uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");
xco+= XIC;
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 8f9bb0d05fe..537996601b8 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -577,30 +577,34 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
/**************** load/replace/save callbacks ******************/
-/* XXX make dynamic */
-static const EnumPropertyItem image_file_type_items[] = {
- {R_TARGA, "TARGA", 0, "Targa", ""},
- {R_RAWTGA, "TARGA RAW", 0, "Targa Raw", ""},
- {R_PNG, "PNG", 0, "PNG", ""},
- {R_BMP, "BMP", 0, "BMP", ""},
- {R_JPEG90, "JPEG", 0, "Jpeg", ""},
+static char *filesel_imagetype_string(Image *ima)
+{
+ char *strp, *str= MEM_callocN(15*32, "menu for filesel");
+
+ strp= str;
+ str += sprintf(str, "Save Image as: %%t|");
+ str += sprintf(str, "Targa %%x%d|", R_TARGA);
+ str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
+ str += sprintf(str, "PNG %%x%d|", R_PNG);
+ str += sprintf(str, "BMP %%x%d|", R_BMP);
+ str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
#ifdef WITH_OPENJPEG
- {R_JP2, "JPEG_2000", 0, "Jpeg 2000", ""},
+ str += sprintf(str, "Jpeg 2000 %%x%d|", R_JP2);
#endif
- {R_IRIS, "IRIS", 0, "Iris", ""},
- //if(G.have_libtiff)
- {R_TIFF, "TIFF", 0, "Tiff", ""},
- {R_RADHDR, "RADIANCE_HDR", 0, "Radiance HDR", ""},
- {R_CINEON, "CINEON", 0, "Cineon", ""},
- {R_DPX, "DPX", 0, "DPX", ""},
+ str += sprintf(str, "Iris %%x%d|", R_IRIS);
+ if(G.have_libtiff)
+ str += sprintf(str, "Tiff %%x%d|", R_TIFF);
+ str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
+ str += sprintf(str, "Cineon %%x%d|", R_CINEON);
+ str += sprintf(str, "DPX %%x%d|", R_DPX);
#ifdef WITH_OPENEXR
- {R_OPENEXR, "OPENEXR", 0, "OpenEXR", ""},
+ str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
/* saving sequences of multilayer won't work, they copy buffers */
- /*if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
- else*/
- {R_MULTILAYER, "MULTILAYER", 0, "MultiLayer", ""},
+ if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
+ else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
#endif
- {0, NULL, 0, NULL, NULL}};
+ return strp;
+}
static void image_filesel(bContext *C, wmOperator *op, const char *path)
{
@@ -795,9 +799,7 @@ static int save_as_exec(bContext *C, wmOperator *op)
if(!ima)
return OPERATOR_CANCELLED;
- sima->imtypenr= RNA_enum_get(op->ptr, "file_type");
RNA_string_get(op->ptr, "filename", str);
-
save_image_doit(C, sima, scene, op, str);
return OPERATOR_FINISHED;
@@ -818,6 +820,10 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* always opens fileselect */
if(ibuf) {
+ char *strp;
+
+ strp= filesel_imagetype_string(ima); // XXX unused still
+
/* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
sima->imtypenr= R_MULTILAYER;
@@ -825,14 +831,14 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
sima->imtypenr= scene->r.imtype;
else
sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
-
- RNA_enum_set(op->ptr, "file_type", sima->imtypenr);
if(ibuf->name[0]==0)
BLI_strncpy(ibuf->name, G.ima, FILE_MAX);
// XXX note: we can give default menu enums to operator for this
image_filesel(C, op, ibuf->name);
+
+ MEM_freeN(strp);
return OPERATOR_RUNNING_MODAL;
}
@@ -856,7 +862,6 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
/* properties */
RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path to save image to.");
- RNA_def_enum(ot->srna, "file_type", image_file_type_items, R_PNG, "File Type", "File type to save image as.");
}
/******************** save image operator ********************/
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 7d6faa00dfc..49f950fe67b 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -327,10 +327,12 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *sce
#endif
if(sima->image) {
ImBuf *ibuf= ED_space_image_buffer(sima);
+ float xuser_asp, yuser_asp;
+ ED_image_aspect(sima->image, &xuser_asp, &yuser_asp);
if(ibuf) {
- width= ibuf->x;
- height= ibuf->y;
+ width= ibuf->x*xuser_asp;
+ height= ibuf->y*yuser_asp;
}
else if(sima->image->type==IMA_TYPE_R_RESULT) {
/* not very important, just nice */
@@ -681,7 +683,7 @@ void ED_image_aspect(Image *ima, float *aspx, float *aspy)
*aspx= *aspy= 1.0;
if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
- (ima->aspx==0.0 || ima->aspy==0.0))
+ (ima->tpageflag & IMA_TILES) || (ima->aspx==0.0 || ima->aspy==0.0))
return;
/* x is always 1 */
diff --git a/source/blender/editors/space_info/Makefile b/source/blender/editors/space_info/Makefile
index 931c2f2097c..bc04ddc7824 100644
--- a/source/blender/editors/space_info/Makefile
+++ b/source/blender/editors/space_info/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index 01268115687..05afcae162e 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -11,4 +11,7 @@ defs = []
if env['WITH_BF_GAMEENGINE']:
defs.append('GAMEBLENDER=1')
+ if env['WITH_BF_SOLID']:
+ defs.append('USE_SUMO_SOLID')
+
env.BlenderLib ( 'bf_editors_space_info', sources, Split(incs), defs, libtype=['core'], priority=[70] )
diff --git a/source/blender/editors/space_info/info_header.c b/source/blender/editors/space_info/info_header.c
index 7d6e2ca05c0..ac39c67d8f2 100644
--- a/source/blender/editors/space_info/info_header.c
+++ b/source/blender/editors/space_info/info_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: info_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -415,7 +415,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
name[len]= '|';
}
- if(0==uiSearchItemAdd(items, name, ot, 0))
+ if(0==uiSearchItemAdd(items, name, ot))
break;
}
}
@@ -491,7 +491,7 @@ void info_header_buttons(const bContext *C, ARegion *ar)
static char search[256]= "";
uiBut *but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, xco+5, yco, 120, 19, "");
- uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
+ uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb);
xco+= 125;
}
diff --git a/source/blender/editors/space_logic/Makefile b/source/blender/editors/space_logic/Makefile
index d5709993368..e07a5bbf4a9 100644
--- a/source/blender/editors/space_logic/Makefile
+++ b/source/blender/editors/space_logic/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_logic/SConscript b/source/blender/editors/space_logic/SConscript
index e32fcc1b535..46a9858a836 100644
--- a/source/blender/editors/space_logic/SConscript
+++ b/source/blender/editors/space_logic/SConscript
@@ -12,4 +12,7 @@ defs = []
if env['WITH_BF_GAMEENGINE']:
defs.append('GAMEBLENDER=1')
+ if env['WITH_BF_SOLID']:
+ defs.append('USE_SUMO_SOLID')
+
env.BlenderLib ( 'bf_editors_space_game', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index b082d5d6ae2..240ddfc2614 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: image_buttons.c 20913 2009-06-16 01:22:56Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_logic/logic_header.c b/source/blender/editors/space_logic/logic_header.c
index d0e905728be..00fc130e771 100644
--- a/source/blender/editors/space_logic/logic_header.c
+++ b/source/blender/editors/space_logic/logic_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: logic_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 55e21561c34..b9385a54d34 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: logic_window.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -3056,12 +3056,12 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ******************************* */
xco= 500; yco= 170; width= 300;
- uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, UI_UNIT_Y, "");
+ uiDefPulldownBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, 19, "");
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_CONT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
+ uiDefButBitS(block, TOG, BUTS_CONT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
uiBlockEndAlign(block);
ob= CTX_data_active_object(C);
@@ -3077,9 +3077,9 @@ void logic_buttons(bContext *C, ARegion *ar)
/* presume it is only objects for now */
uiBlockBeginAlign(block);
// if(ob->controllers.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
+ uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
// if(ob->controllers.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
+ uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
uiBlockEndAlign(block);
yco-=20;
@@ -3100,7 +3100,7 @@ void logic_buttons(bContext *C, ARegion *ar)
if(ob->scaflag & OB_SHOWCONT) {
/* first show the state */
- uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, UI_UNIT_Y, "Object state menu: store and retrieve initial state");
+ uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, 19, "Object state menu: store and retrieve initial state");
if (!ob->state)
ob->state = 1;
@@ -3116,9 +3116,9 @@ void logic_buttons(bContext *C, ARegion *ar)
}
}
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+226), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set all state bits");
- uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+248), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set the initial state");
- uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D",(short)(xco+270), yco-10, 15, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Print state debug info");
+ uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+226), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set all state bits");
+ uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+248), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set the initial state");
+ uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D",(short)(xco+270), yco-10, 15, 19, &ob->scaflag, 0, 0, 0, 0, "Print state debug info");
uiBlockEndAlign(block);
yco-=35;
@@ -3142,17 +3142,17 @@ void logic_buttons(bContext *C, ARegion *ar)
if (act)
act->flag |= ACT_VISIBLE;
}
- uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Delete Controller");
- uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Controller settings");
- uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)");
+ uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller");
+ uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings");
+ uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)");
sprintf(name, "%d", first_bit(cont->state_mask)+1);
- uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, UI_UNIT_Y, "Set controller state index (from 1 to 30)");
+ uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)");
if(cont->flag & CONT_SHOW) {
cont->otype= cont->type;
- uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 70, UI_UNIT_Y, &cont->type, 0, 0, 0, 0, "Controller type");
- but= uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont->name, 0, 31, 0, 0, "Controller name");
+ uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 70, 19, &cont->type, 0, 0, 0, 0, "Controller type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), 19, cont->name, 0, 31, 0, 0, "Controller name");
uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0);
ycoo= yco;
@@ -3162,17 +3162,17 @@ void logic_buttons(bContext *C, ARegion *ar)
else {
cpack(0x999999);
glRecti(xco+22, yco, xco+width-22,yco+19);
- but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller type");
+ but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, 19, cont, 0, 0, 0, 0, "Controller type");
uiButSetFunc(but, sca_move_controller, cont, NULL);
- but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-158), UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller name");
+ but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-158), 19, cont, 0, 0, 0, 0, "Controller name");
uiButSetFunc(but, sca_move_controller, cont, NULL);
ycoo= yco;
}
- but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
- uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
+ uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, "");
/* offset is >0 if at least one controller was displayed */
offset++;
yco-=20;
@@ -3188,13 +3188,13 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ******************************* */
xco= 10; yco= 170; width= 400;
- uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, UI_UNIT_Y, "");
+ uiDefPulldownBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, 19, "");
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
- uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states");
+ uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+ uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states");
uiBlockEndAlign(block);
for(a=0; a<count; a++) {
@@ -3207,9 +3207,9 @@ void logic_buttons(bContext *C, ARegion *ar)
/* presume it is only objects for now */
uiBlockBeginAlign(block);
// if(ob->sensors.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
+ uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
// if(ob->sensors.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
+ uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
uiBlockEndAlign(block);
yco-=20;
@@ -3226,17 +3226,17 @@ void logic_buttons(bContext *C, ARegion *ar)
pin = (slogic->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1:0 ;
sens->flag |= SENS_VISIBLE;
- uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
+ uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
if (pin)
- uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
+ uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
- uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Sensor settings");
+ uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings");
ycoo= yco;
if(sens->flag & SENS_SHOW)
{
- uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 80, UI_UNIT_Y, &sens->type, 0, 0, 0, 0, "Sensor type");
- but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens->name, 0, 31, 0, 0, "Sensor name");
+ uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 80, 19, &sens->type, 0, 0, 0, 0, "Sensor type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens->name, 0, 31, 0, 0, "Sensor name");
uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0);
sens->otype= sens->type;
@@ -3246,13 +3246,13 @@ void logic_buttons(bContext *C, ARegion *ar)
else {
set_col_sensor(sens->type, 1);
glRecti(xco+22, yco, xco+width-22,yco+19);
- but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 80, UI_UNIT_Y, sens, 0, 0, 0, 0, "");
+ but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 80, 19, sens, 0, 0, 0, 0, "");
uiButSetFunc(but, sca_move_sensor, sens, NULL);
- but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens, 0, 31, 0, 0, "");
+ but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens, 0, 31, 0, 0, "");
uiButSetFunc(but, sca_move_sensor, sens, NULL);
}
- but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
yco-=20;
@@ -3266,13 +3266,13 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ******************************* */
xco= 900; yco= 170; width= 400;
- uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, UI_UNIT_Y, "");
+ uiDefPulldownBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, 19, "");
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
- uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states");
+ uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+ uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states");
uiBlockEndAlign(block);
for(a=0; a<count; a++) {
ob= (Object *)idar[a];
@@ -3283,9 +3283,9 @@ void logic_buttons(bContext *C, ARegion *ar)
/* presume it is only objects for now */
uiBlockBeginAlign(block);
// if(ob->actuators.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
+ uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
// if(ob->actuators.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
+ uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
uiBlockEndAlign(block);
yco-=20;
@@ -3301,15 +3301,15 @@ void logic_buttons(bContext *C, ARegion *ar)
pin = (slogic->scaflag & BUTS_ACT_STATE && (act->flag & SENS_SHOW || act->flag & SENS_PIN)) ? 1:0 ;
act->flag |= ACT_VISIBLE; /* mark the actuator as visible to help implementing the up/down action */
- uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Delete Actuator");
+ uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator");
if (pin)
- uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
- uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display the actuator");
+ uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
+ uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display the actuator");
if(act->flag & ACT_SHOW) {
act->otype= act->type;
- uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 90, UI_UNIT_Y, &act->type, 0, 0, 0, 0, "Actuator type");
- but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act->name, 0, 31, 0, 0, "Actuator name");
+ uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 90, 19, &act->type, 0, 0, 0, 0, "Actuator type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act->name, 0, 31, 0, 0, "Actuator name");
uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0);
ycoo= yco;
@@ -3319,14 +3319,14 @@ void logic_buttons(bContext *C, ARegion *ar)
else {
set_col_actuator(act->type, 1);
glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19));
- but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator type");
+ but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, 19, act, 0, 0, 0, 0, "Actuator type");
uiButSetFunc(but, sca_move_actuator, act, NULL);
- but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator name");
+ but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act, 0, 0, 0, 0, "Actuator name");
uiButSetFunc(but, sca_move_actuator, act, NULL);
ycoo= yco;
}
- uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
+ uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, "");
yco-=20;
}
diff --git a/source/blender/editors/space_nla/Makefile b/source/blender/editors/space_nla/Makefile
index d7c9477dc83..43f010e6adc 100644
--- a/source/blender/editors/space_nla/Makefile
+++ b/source/blender/editors/space_nla/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c
index 0f6b77da6f5..2366a888d3b 100644
--- a/source/blender/editors/space_nla/nla_header.c
+++ b/source/blender/editors/space_nla/nla_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: nla_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_node/Makefile b/source/blender/editors/space_node/Makefile
index 5bd6e95e28c..60f81255a74 100644
--- a/source/blender/editors/space_node/Makefile
+++ b/source/blender/editors/space_node/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index f2e2486075b..0670dd9e01f 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: drawnode.c 17439 2008-11-13 09:57:11Z kakbarnf $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 8c48d4b54e1..1031ad213f4 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: node_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_outliner/Makefile b/source/blender/editors/space_outliner/Makefile
index 8d7cd017e0b..19d40a4a31e 100644
--- a/source/blender/editors/space_outliner/Makefile
+++ b/source/blender/editors/space_outliner/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index 8017b8437ff..16748af39d5 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -1031,7 +1031,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
PointerRNA pptr, propptr, *ptr= (PointerRNA*)idv;
- PropertyRNA *prop, *iterprop;
+ PropertyRNA *prop, *iterprop, *nameprop;
PropertyType proptype;
PropertySubType propsubtype;
int a, tot;
@@ -1043,10 +1043,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
else if(type == TSE_RNA_STRUCT) {
/* struct */
- te->name= RNA_struct_name_get_alloc(ptr, NULL, 0);
+ nameprop= RNA_struct_name_property(ptr->type);
- if(te->name)
+ if(nameprop) {
+ te->name= RNA_property_string_get_alloc(ptr, nameprop, NULL, 0);
te->flag |= TE_FREE_NAME;
+ }
else
te->name= (char*)RNA_struct_ui_name(ptr->type);
@@ -3073,7 +3075,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
TreeElement *tem, *temnext, *temsub;
TreeStoreElem *tse, *tsenext;
PointerRNA *ptr, *nextptr;
- PropertyRNA *prop;
+ PropertyRNA *prop, *nameprop;
char *newpath=NULL;
/* optimise tricks:
@@ -3117,16 +3119,17 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
newpath= RNA_path_append(*path, ptr, prop, 0, NULL);
}
else if(RNA_property_type(prop) == PROP_COLLECTION) {
- char buf[128], *name;
-
temnext= (TreeElement*)(ld->next->data);
tsenext= TREESTORE(temnext);
nextptr= &temnext->rnaptr;
- name= RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf));
+ nameprop= RNA_struct_name_property(nextptr->type);
- if(name) {
+ if(nameprop) {
/* if possible, use name as a key in the path */
+ char buf[128], *name;
+ name= RNA_property_string_get_alloc(nextptr, nameprop, buf, sizeof(buf));
+
newpath= RNA_path_append(*path, NULL, prop, 0, name);
if(name != buf)
diff --git a/source/blender/editors/space_outliner/outliner_header.c b/source/blender/editors/space_outliner/outliner_header.c
index fe2f054899c..b630eb2acf3 100644
--- a/source/blender/editors/space_outliner/outliner_header.c
+++ b/source/blender/editors/space_outliner/outliner_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: outliner_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 4ddb586beb4..cc7880fcae7 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: space_outliner.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_script/Makefile b/source/blender/editors/space_script/Makefile
index 3322cb61a7f..48e1cd8e861 100644
--- a/source/blender/editors/space_script/Makefile
+++ b/source/blender/editors/space_script/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_script/script_header.c b/source/blender/editors/space_script/script_header.c
index d9851df4185..548ed8d2331 100644
--- a/source/blender/editors/space_script/script_header.c
+++ b/source/blender/editors/space_script/script_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: script_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_sequencer/Makefile b/source/blender/editors/space_sequencer/Makefile
index 7be0bc9cfef..80699db4baa 100644
--- a/source/blender/editors/space_sequencer/Makefile
+++ b/source/blender/editors/space_sequencer/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index cc4f5cf5ce3..f127ab4b0cf 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: sequencer_buttons.c 20279 2009-05-19 17:13:33Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_sound/Makefile b/source/blender/editors/space_sound/Makefile
index a072684d543..4d375282223 100644
--- a/source/blender/editors/space_sound/Makefile
+++ b/source/blender/editors/space_sound/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_sound/sound_header.c b/source/blender/editors/space_sound/sound_header.c
index ae3410663c2..b674438210d 100644
--- a/source/blender/editors/space_sound/sound_header.c
+++ b/source/blender/editors/space_sound/sound_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: sound_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_text/Makefile b/source/blender/editors/space_text/Makefile
index 50871017085..33e12dc1abb 100644
--- a/source/blender/editors/space_text/Makefile
+++ b/source/blender/editors/space_text/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index c761587198f..1a3f998bb8a 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: text_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -88,7 +88,6 @@
/* ************************ header area region *********************** */
#ifndef DISABLE_PYTHON
-#if 0
static void do_text_template_scriptsmenu(bContext *C, void *arg, int event)
{
// XXX BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
@@ -155,7 +154,6 @@ static uiBlock *text_plugin_scriptsmenu(bContext *C, void *args_unused)
return block;
}
#endif
-#endif
/************************** properties ******************************/
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
index 4fa54cdf27b..e4c697dc2b5 100644
--- a/source/blender/editors/space_text/text_python.c
+++ b/source/blender/editors/space_text/text_python.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: text_python.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_time/Makefile b/source/blender/editors/space_time/Makefile
index e0bf3943dd8..20877b48559 100644
--- a/source/blender/editors/space_time/Makefile
+++ b/source/blender/editors/space_time/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index c4ca4d8522f..67759bb1b46 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: space_time.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c
index 29f31671670..2b00459fc17 100644
--- a/source/blender/editors/space_time/time_header.c
+++ b/source/blender/editors/space_time/time_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: time_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -567,12 +567,12 @@ void time_header_buttons(const bContext *C, ARegion *ar)
uiBlockBeginAlign(block);
uiDefIconButBitS(block, TOG, AUTOKEY_ON, B_REDRAWALL, ICON_REC,
- xco, yco, XIC, YIC, &(scene->toolsettings->autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones");
+ xco, yco, XIC, YIC, &(scene->autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones");
xco+= XIC;
if (IS_AUTOKEY_ON(scene)) {
uiDefButS(block, MENU, B_REDRAWALL,
"Auto-Keying Mode %t|Add/Replace Keys%x3|Replace Keys %x5",
- xco, yco, (int)5.5*XIC, YIC, &(scene->toolsettings->autokey_mode), 0, 1, 0, 0,
+ xco, yco, (int)5.5*XIC, YIC, &(scene->autokey_mode), 0, 1, 0, 0,
"Mode of automatic keyframe insertion for Objects and Bones");
xco+= (6*XIC);
}
diff --git a/source/blender/editors/space_view3d/Makefile b/source/blender/editors/space_view3d/Makefile
index 5e6f8a6c426..dd4eab89411 100644
--- a/source/blender/editors/space_view3d/Makefile
+++ b/source/blender/editors/space_view3d/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 05490e2fce1..a67e8c8a1c3 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -117,7 +117,7 @@
(vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
#define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
-( (sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
+( (sce->selectmode & SCE_SELECT_FACE) && \
(vd->drawtype<=OB_SOLID) && \
(((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
)
@@ -1493,14 +1493,14 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
{
- ToolSettings *ts= ((Scene *)userData)->toolsettings;
+ Scene *scene= (Scene *)userData;
EditFace *efa = EM_get_face_for_index(index);
if (efa->h==0 && efa->fgonf!=EM_FGON) {
glVertex3fv(cent);
- glVertex3f( cent[0] + no[0]*ts->normalsize,
- cent[1] + no[1]*ts->normalsize,
- cent[2] + no[2]*ts->normalsize);
+ glVertex3f( cent[0] + no[0]*scene->editbutsize,
+ cent[1] + no[1]*scene->editbutsize,
+ cent[2] + no[2]*scene->editbutsize);
}
}
static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
@@ -1529,20 +1529,19 @@ static void draw_dm_face_centers(DerivedMesh *dm, int sel)
static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
Scene *scene= (Scene *)userData;
- ToolSettings *ts= scene->toolsettings;
EditVert *eve = EM_get_vert_for_index(index);
if (eve->h==0) {
glVertex3fv(co);
if (no_f) {
- glVertex3f( co[0] + no_f[0]*ts->normalsize,
- co[1] + no_f[1]*ts->normalsize,
- co[2] + no_f[2]*ts->normalsize);
+ glVertex3f( co[0] + no_f[0]*scene->editbutsize,
+ co[1] + no_f[1]*scene->editbutsize,
+ co[2] + no_f[2]*scene->editbutsize);
} else {
- glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
- co[1] + no_s[1]*ts->normalsize/32767.0f,
- co[2] + no_s[2]*ts->normalsize/32767.0f);
+ glVertex3f( co[0] + no_s[0]*scene->editbutsize/32767.0f,
+ co[1] + no_s[1]*scene->editbutsize/32767.0f,
+ co[2] + no_s[2]*scene->editbutsize/32767.0f);
}
}
}
@@ -1763,9 +1762,7 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, floa
}
static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
{
- ToolSettings *ts= scene->toolsettings;
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (scene->selectmode & SCE_SELECT_VERTEX) {
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
bglBegin(GL_POINTS);
dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
@@ -1789,7 +1786,6 @@ static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
{
- ToolSettings *ts= scene->toolsettings;
int sel;
if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
@@ -1821,7 +1817,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
col[3] = fcol[3] = 255;
}
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(scene->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size);
glColor4ubv((GLubyte *)col);
draw_dm_verts(cageDM, sel, eve_act);
@@ -1846,7 +1842,6 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
{
- ToolSettings *ts= scene->toolsettings;
int pass;
unsigned char wireCol[4], selCol[4], actCol[4];
@@ -1876,11 +1871,11 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
if (!sel_only) wireCol[3] = 255;
}
- if(ts->selectmode == SCE_SELECT_FACE) {
+ if(scene->selectmode == SCE_SELECT_FACE) {
draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
}
- else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
- if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
+ else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {
+ if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
glShadeModel(GL_SMOOTH);
draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
glShadeModel(GL_FLAT);
@@ -3244,9 +3239,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(draw_as!=PART_DRAW_PATH){
state.time=cfra;
if(psys_get_particle_state(scene,ob,psys,a,&state,0)){
- if(psys->parent)
- Mat4MulVecfl(psys->parent->obmat, state.co);
-
/* create actiual particle data */
switch(draw_as){
case PART_DRAW_DOT:
@@ -3669,13 +3661,13 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
}
/* draw edit vertices */
- if(pset->selectmode!=SCE_SELECT_PATH){
+ if(scene->selectmode!=SCE_SELECT_PATH){
glDisableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisable(GL_LIGHTING);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- if(pset->selectmode==SCE_SELECT_POINT){
+ if(scene->selectmode==SCE_SELECT_POINT){
float *cd=0,*cdata=0;
cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
@@ -3714,7 +3706,7 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
MEM_freeN(cdata);
cd=cdata=0;
}
- else if(pset->selectmode == SCE_SELECT_END){
+ else if(scene->selectmode == SCE_SELECT_END){
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
if((pa->flag & PARS_HIDE)==0){
key = edit->keys[i] + pa->totkey - 1;
@@ -3952,7 +3944,6 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, int dt)
{
- ToolSettings *ts= scene->toolsettings;
Object *ob= base->object;
Curve *cu = ob->data;
Nurb *nu;
@@ -3984,7 +3975,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
/* direction vectors for 3d curve paths
when at its lowest, dont render normals */
- if(cu->flag & CU_3D && ts->normalsize > 0.0015) {
+ if(cu->flag & CU_3D && scene->editbutsize > 0.0015) {
UI_ThemeColor(TH_WIRE);
for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
BevPoint *bevp= (BevPoint *)(bl+1);
@@ -3992,7 +3983,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
int skip= nu->resolu/16;
while (nr-->0) { /* accounts for empty bevel lists */
- float fac= bevp->radius * ts->normalsize;
+ float fac= bevp->radius * scene->editbutsize;
float ox,oy,oz; // Offset perpendicular to the curve
float dx,dy,dz; // Delta along the curve
@@ -5414,7 +5405,6 @@ static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob)
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
{
- ToolSettings *ts= scene->toolsettings;
wmMultMatrix(ob->obmat);
@@ -5432,8 +5422,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
EM_init_index_arrays(em, 1, 1, 1);
- bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
- if(ts->selectmode & SCE_SELECT_FACE)
+ bbs_mesh_solid_EM(scene, v3d, ob, dm, scene->selectmode & SCE_SELECT_FACE);
+ if(scene->selectmode & SCE_SELECT_FACE)
em_solidoffs = 1+em->totface;
else
em_solidoffs= 1;
@@ -5445,7 +5435,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
em_wireoffs= em_solidoffs + em->totedge;
// we draw verts if vert select mode or if in transform (for snap).
- if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
+ if(scene->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
bbs_mesh_verts(dm, em_wireoffs);
em_vertoffs= em_wireoffs + em->totvert;
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 625b1838951..2d6a57d5a34 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -122,24 +122,6 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
return arnew;
}
-/* ****************************************************** */
-
-/* function to always find a regionview3d context inside 3D window */
-RegionView3D *ED_view3d_context_rv3d(bContext *C)
-{
- RegionView3D *rv3d= CTX_wm_region_view3d(C);
-
- if(rv3d==NULL) {
- ScrArea *sa =CTX_wm_area(C);
- if(sa->spacetype==SPACE_VIEW3D) {
- ARegion *ar;
- for(ar= sa->regionbase.first; ar; ar= ar->next)
- if(ar->regiontype==RGN_TYPE_WINDOW)
- return ar->regiondata;
- }
- }
- return rv3d;
-}
/* ******************** default callbacks for view3d space ***************** */
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 91565235591..b6e9e05b120 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1663,7 +1663,7 @@ static void view3d_panel_bonesketch_spaces(const bContext *C, Panel *pa)
uiBlockEndAlign(block);
- uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_NOP, "Peel Objects", 10, yco, 200, 20, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
+ uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_NOP, "Peel Objects", 10, yco, 200, 20, &scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
}
@@ -1710,7 +1710,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
}
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(C, pa->layout, &ptr, 2);
+ uiDefAutoButsRNA(C, pa->layout, &ptr);
}
void view3d_buttons_register(ARegionType *art)
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 79ea90864f3..1c528aac6a3 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: view3d_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -1812,7 +1812,6 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
{
#if 0
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
switch(event) {
case 1:
@@ -1871,22 +1870,22 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
Transform();
break;
case 15:
- ts->snap_flag &= ~SCE_SNAP;
+ scene->snap_flag &= ~SCE_SNAP;
break;
case 16:
- ts->snap_flag |= SCE_SNAP;
+ scene->snap_flag |= SCE_SNAP;
break;
case 17:
- ts->snap_target = SCE_SNAP_TARGET_CLOSEST;
+ scene->snap_target = SCE_SNAP_TARGET_CLOSEST;
break;
case 18:
- ts->snap_target = SCE_SNAP_TARGET_CENTER;
+ scene->snap_target = SCE_SNAP_TARGET_CENTER;
break;
case 19:
- ts->snap_target = SCE_SNAP_TARGET_MEDIAN;
+ scene->snap_target = SCE_SNAP_TARGET_MEDIAN;
break;
case 20:
- ts->snap_target = SCE_SNAP_TARGET_ACTIVE;
+ scene->snap_target = SCE_SNAP_TARGET_ACTIVE;
break;
case 21:
alignmenu();
@@ -1897,7 +1896,7 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
uiBlock *block;
short yco = 20, menuwidth = 120;
@@ -1949,7 +1948,7 @@ static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
{
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
- if (ts->snap_flag & SCE_SNAP)
+ if (scene->snap_flag & SCE_SNAP)
{
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Grid", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
@@ -1962,7 +1961,7 @@ static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
- switch(ts->snap_target)
+ switch(scene->snap_target)
{
case SCE_SNAP_TARGET_CLOSEST:
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
@@ -2651,34 +2650,34 @@ static uiBlock *view3d_edit_objectmenu(bContext *C, ARegion *ar, void *arg_unuse
static void do_view3d_edit_propfalloffmenu(bContext *C, void *arg, int event)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
- ts->prop_mode= event;
+ scene->prop_mode= event;
}
static uiBlock *view3d_edit_propfalloffmenu(bContext *C, ARegion *ar, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
uiBlock *block;
short yco = 20, menuwidth = 120;
block= uiBeginBlock(C, ar, "view3d_edit_propfalloffmenu", UI_EMBOSSP);
uiBlockSetButmFunc(block, do_view3d_edit_propfalloffmenu, NULL);
- if (ts->prop_mode==PROP_SMOOTH) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
+ if (scene->prop_mode==PROP_SMOOTH) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
- if (ts->prop_mode==PROP_SPHERE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
+ if (scene->prop_mode==PROP_SPHERE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
- if (ts->prop_mode==PROP_ROOT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
+ if (scene->prop_mode==PROP_ROOT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
- if (ts->prop_mode==PROP_SHARP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
+ if (scene->prop_mode==PROP_SHARP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
- if (ts->prop_mode==PROP_LIN) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
+ if (scene->prop_mode==PROP_LIN) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
- if (ts->prop_mode==PROP_RANDOM) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
+ if (scene->prop_mode==PROP_RANDOM) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
- if (ts->prop_mode==PROP_CONST) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
+ if (scene->prop_mode==PROP_CONST) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
uiBlockSetDirection(block, UI_RIGHT);
@@ -2699,7 +2698,7 @@ void do_view3d_edit_mesh_verticesmenu(bContext *C, void *arg, int event)
make_parent();
break;
case 1: /* remove doubles */
- count= removedoublesflag(1, 0, ts->doublimit);
+ count= removedoublesflag(1, 0, scene->toolsettings->doublimit);
notice("Removed: %d", count);
if (count) { /* only undo and redraw if an action is taken */
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
@@ -2769,18 +2768,18 @@ void do_view3d_edit_mesh_edgesmenu(bContext *C, void *arg, int event)
switch(event) {
case 0: /* subdivide smooth */
- esubdivideflag(1, 0.0, ts->editbutflag | B_SMOOTH,1,0);
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag | B_SMOOTH,1,0);
ED_undo_push(C, "Subdivide Smooth");
break;
case 1: /*subdivide fractal */
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
- esubdivideflag(1, fac, ts->editbutflag,1,0);
+ esubdivideflag(1, fac, scene->toolsettings->editbutflag,1,0);
ED_undo_push(C, "Subdivide Fractal");
break;
case 2: /* subdivide */
- esubdivideflag(1, 0.0, ts->editbutflag,1,0);
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag,1,0);
ED_undo_push(C, "Subdivide");
break;
case 3: /* knife subdivide */
@@ -3143,7 +3142,6 @@ static uiBlock *view3d_edit_mesh_scriptsmenu(bContext *C, ARegion *ar, void *arg
static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
{
#if 0
- ToolSettings *ts= CTX_data_tool_settings(C);
Scene *scene= CTX_data_scene(C);
ScrArea *sa= CTX_wm_area(C);
View3D *v3d= sa->spacedata.first;
@@ -3187,12 +3185,12 @@ static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
Transform();
break;
case 12: /* proportional edit (toggle) */
- if(ts->proportional) ts->proportional= 0;
- else ts->proportional= 1;
+ if(scene->proportional) scene->proportional= 0;
+ else scene->proportional= 1;
break;
case 13: /* automerge edit (toggle) */
- if(ts->automerge) ts->automerge= 0;
- else ts->automerge= 1;
+ if(scene->automerge) scene->automerge= 0;
+ else scene->automerge= 1;
break;
case 15:
uv_autocalc_tface();
@@ -3206,7 +3204,7 @@ static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
uiBlock *block;
short yco= 0, menuwidth=120;
@@ -3252,7 +3250,7 @@ static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
- if(ts->proportional) {
+ if(scene->proportional) {
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
} else {
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
@@ -3263,7 +3261,7 @@ static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
/* PITA but we should let users know that automerge cant work with multires :/ */
uiDefIconTextBut(block, BUTM, 1,
- ts->automerge ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
+ scene->automerge ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
((Mesh*)obedit->data)->mr ? "AutoMerge Editing (disabled by multires)" : "AutoMerge Editing",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
@@ -3538,8 +3536,8 @@ static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
Transform();
break;
case 5: /* proportional edit (toggle) */
- if(ts->proportional) ts->proportional= 0;
- else ts->proportional= 1;
+ if(scene->proportional) scene->proportional= 0;
+ else scene->proportional= 1;
break;
case 7: /* delete keyframe */
common_deletekey();
@@ -3550,7 +3548,7 @@ static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
static uiBlock *view3d_edit_latticemenu(bContext *C, ARegion *ar, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
uiBlock *block;
short yco= 0, menuwidth=120;
@@ -3576,7 +3574,7 @@ static uiBlock *view3d_edit_latticemenu(bContext *C, ARegion *ar, void *arg_unus
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
- if(ts->proportional) {
+ if(scene->proportional) {
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
} else {
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
@@ -4697,7 +4695,7 @@ static uiBlock *view3d_faceselmenu(bContext *C, ARegion *ar, void *arg_unused)
static void view3d_select_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
uiItemO(layout, NULL, 0, "VIEW3D_OT_select_border");
@@ -4706,7 +4704,7 @@ static void view3d_select_particlemenu(bContext *C, uiLayout *layout, void *arg_
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_all_toggle");
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_linked");
- if(ts->particle.selectmode & SCE_SELECT_POINT) {
+ if(scene->selectmode & SCE_SELECT_POINT) {
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last"); // |W, 4
uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first"); // |W, 3
}
@@ -4726,7 +4724,7 @@ static void view3d_particle_showhidemenu(bContext *C, uiLayout *layout, void *ar
static void view3d_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
{
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
// XXX uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Particle Edit Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
// add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
@@ -4741,7 +4739,7 @@ static void view3d_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles"); // |W, 5
uiItemO(layout, NULL, 0, "PARTICLE_OT_delete");
- if(ts->particle.selectmode & SCE_SELECT_POINT)
+ if(scene->selectmode & SCE_SELECT_POINT)
uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide"); // |W, 2
uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey"); // |W, 1
@@ -4875,7 +4873,6 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
{
wmWindow *win= CTX_wm_window(C);
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
ScrArea *sa= CTX_wm_area(C);
View3D *v3d= sa->spacedata.first;
Base *basact= CTX_data_active_base(C);
@@ -5010,7 +5007,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
if(em) {
if(shift==0 || em->selectmode==0)
em->selectmode= SCE_SELECT_VERTEX;
- ts->selectmode= em->selectmode;
+ scene->selectmode= em->selectmode;
EM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Vertex");
@@ -5024,7 +5021,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
}
em->selectmode = SCE_SELECT_EDGE;
}
- ts->selectmode= em->selectmode;
+ scene->selectmode= em->selectmode;
EM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Edge");
@@ -5033,12 +5030,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
case B_SEL_FACE:
if(em) {
if( shift==0 || em->selectmode==0){
- if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
- if(ctrl) EM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+ if( ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
+ if(ctrl) EM_convertsel(em, (scene->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
}
em->selectmode = SCE_SELECT_FACE;
}
- ts->selectmode= em->selectmode;
+ scene->selectmode= em->selectmode;
EM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Face");
@@ -5046,15 +5043,15 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
break;
case B_SEL_PATH:
- ts->particle.selectmode= SCE_SELECT_PATH;
+ scene->selectmode= SCE_SELECT_PATH;
ED_undo_push(C, "Selectmode Set: Path");
break;
case B_SEL_POINT:
- ts->particle.selectmode = SCE_SELECT_POINT;
+ scene->selectmode = SCE_SELECT_POINT;
ED_undo_push(C, "Selectmode Set: Point");
break;
case B_SEL_END:
- ts->particle.selectmode = SCE_SELECT_END;
+ scene->selectmode = SCE_SELECT_END;
ED_undo_push(C, "Selectmode Set: End point");
break;
@@ -5283,7 +5280,6 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
ScrArea *sa= CTX_wm_area(C);
View3D *v3d= sa->spacedata.first;
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
Object *ob= OBACT;
Object *obedit = CTX_data_edit_object(C);
uiBlock *block;
@@ -5453,11 +5449,11 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
if((obedit && (obedit->type == OB_MESH || obedit->type == OB_CURVE || obedit->type == OB_SURF || obedit->type == OB_LATTICE)) || G.f & G_PARTICLEEDIT) {
uiBlockBeginAlign(block);
- uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,yco,XIC+10,YIC, &(ts->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,yco,XIC+10,YIC, &(scene->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
xco+= XIC+10;
- if(ts->proportional) {
- uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SMOOTHCURVE, propfalloff_pup(), xco,yco,XIC+10,YIC, &(ts->prop_mode), 0.0, 0.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
+ if(scene->proportional) {
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SMOOTHCURVE, propfalloff_pup(), xco,yco,XIC+10,YIC, &(scene->prop_mode), 0.0, 0.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
xco+= XIC+10;
}
uiBlockEndAlign(block);
@@ -5468,21 +5464,21 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
if (BIF_snappingSupported(obedit)) {
uiBlockBeginAlign(block);
- if (ts->snap_flag & SCE_SNAP) {
- uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
xco+= XIC;
- uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");
+ uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");
xco+= XIC;
- if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) {
- uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, ICON_SNAP_PEEL_OBJECT,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");
+ if (scene->snap_mode == SCE_SNAP_MODE_VOLUME) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, ICON_SNAP_PEEL_OBJECT,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");
xco+= XIC;
}
- uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(ts->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(scene->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
xco+= XIC;
- uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &ts->snap_target, 0, 0, 0, 0, "Snap Target Mode");
+ uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode");
xco+= XIC+70;
} else {
- uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
xco+= XIC;
}
@@ -5513,11 +5509,11 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
}
else if(G.f & G_PARTICLEEDIT) {
uiBlockBeginAlign(block);
- uiDefIconButBitI(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Path edit mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode");
xco+= XIC;
- uiDefIconButBitI(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Point select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode");
xco+= XIC;
- uiDefIconButBitI(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Tip select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode");
xco+= XIC;
uiBlockEndAlign(block);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index a153f795292..e0e8ac7c7a7 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -438,7 +438,6 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, in
static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select)
{
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data;
- ToolSettings *ts= vc->scene->toolsettings;
rcti rect;
int bbsel;
@@ -457,14 +456,14 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, select);
} else {
mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
@@ -476,7 +475,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, select);
} else {
@@ -1278,7 +1277,6 @@ static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int
static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } data;
- ToolSettings *ts= vc->scene->toolsettings;
int bbsel;
data.vc= *vc;
@@ -1289,14 +1287,14 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, select);
} else {
mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
@@ -1308,7 +1306,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, select);
} else {
@@ -1641,7 +1639,6 @@ static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y
static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
{
- ToolSettings *ts= vc->scene->toolsettings;
int bbsel;
if(vc->obedit==NULL && (FACESEL_PAINT_TEST)) {
@@ -1669,7 +1666,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
data.mval[1] = mval[1];
data.radius = rad;
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
if(bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1677,7 +1674,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
if (bbsel) {
EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1685,7 +1682,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE);
} else {
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index ea365d59ac7..1e55f2e4a9a 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -120,6 +120,8 @@ static void redo_cb(bContext *C, void *arg_op, void *arg2)
static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
{
+ /* XXX temp */
+ extern void uiDefAutoButsRNA_single(const bContext *C, uiLayout *layout, PointerRNA *ptr);
wmWindowManager *wm= CTX_wm_manager(C);
wmOperator *op;
PointerRNA ptr;
@@ -134,7 +136,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
if(op==NULL)
return;
- if(op->type->poll && op->type->poll((bContext *)C)==0)
+ if(op->type->poll && op->type->poll(C)==0)
return;
uiBlockSetFunc(block, redo_cb, op, NULL);
@@ -145,132 +147,13 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
}
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(C, pa->layout, &ptr, 1);
+ uiDefAutoButsRNA_single(C, pa->layout, &ptr);
}
-/* ******************* */
-
-typedef struct CustomTool {
- struct CustomTool *next, *prev;
- char opname[OP_MAX_TYPENAME];
-} CustomTool;
-
-static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2)
-{
- wmOperatorType *ot= arg2;
-
- if(ot) {
- CustomTool *ct= MEM_callocN(sizeof(CustomTool), "CustomTool");
-
- BLI_addtail(arg_listbase, ct);
- BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME);
- }
-
-}
-
-static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
-{
- wmOperatorType *ot = WM_operatortype_first();
-
- for(; ot; ot= ot->next) {
-
- if(BLI_strcasestr(ot->name, str)) {
- if(ot->poll==NULL || ot->poll((bContext *)C)) {
-
- if(0==uiSearchItemAdd(items, ot->name, ot, 0))
- break;
- }
- }
- }
-}
-
-
-/* ID Search browse menu, open */
-static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase)
-{
- static char search[OP_MAX_TYPENAME];
- wmEvent event;
- wmWindow *win= CTX_wm_window(C);
- uiBlock *block;
- uiBut *but;
-
- /* clear initial search string, then all items show */
- search[0]= 0;
-
- block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
-
- /* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
-
- but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, OP_MAX_TYPENAME, 10, 0, 150, 19, "");
- uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL);
-
- uiBoundsBlock(block, 6);
- uiBlockSetDirection(block, UI_DOWN);
- uiEndBlock(C, block);
-
- event= *(win->eventstate); /* XXX huh huh? make api call */
- event.type= EVT_BUT_OPEN;
- event.val= KM_PRESS;
- event.customdata= but;
- event.customdatafree= FALSE;
- wm_event_add(win, &event);
-
- return block;
-}
-
-
-static void view3d_panel_tools(const bContext *C, Panel *pa)
-{
- static ListBase tools= {NULL, NULL};
- Object *obedit= CTX_data_edit_object(C);
-// Object *obact = CTX_data_active_object(C);
- uiLayout *col;
-
- if(obedit) {
- if(obedit->type==OB_MESH) {
-
- col= uiLayoutColumn(pa->layout, 1);
- uiItemFullO(col, NULL, 0, "MESH_OT_spin", NULL, WM_OP_INVOKE_REGION_WIN);
- uiItemFullO(col, NULL, 0, "MESH_OT_screw", NULL, WM_OP_INVOKE_REGION_WIN);
-
- if(tools.first) {
- CustomTool *ct;
-
- for(ct= tools.first; ct; ct= ct->next) {
- col= uiLayoutColumn(pa->layout, 1);
- uiItemFullO(col, NULL, 0, ct->opname, NULL, WM_OP_INVOKE_REGION_WIN);
- }
- }
- col= uiLayoutColumn(pa->layout, 1);
- uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &tools, "Add Operator", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add tool");
- }
- }
- else {
-
- col= uiLayoutColumn(pa->layout, 1);
- uiItemFullO(col, NULL, 0, "OBJECT_OT_delete", NULL, WM_OP_INVOKE_REGION_WIN);
- uiItemFullO(col, NULL, 0, "OBJECT_OT_primitive_add", NULL, WM_OP_INVOKE_REGION_WIN);
-
- col= uiLayoutColumn(pa->layout, 1);
- uiItemFullO(col, NULL, 0, "OBJECT_OT_parent_set", NULL, WM_OP_INVOKE_REGION_WIN);
- uiItemFullO(col, NULL, 0, "OBJECT_OT_parent_clear", NULL, WM_OP_INVOKE_REGION_WIN);
-
- }
-}
-
-
void view3d_toolbar_register(ARegionType *art)
{
PanelType *pt;
- pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
- strcpy(pt->idname, "VIEW3D_PT_tools");
- strcpy(pt->label, "Tools");
- pt->draw= view3d_panel_tools;
- BLI_addtail(&art->paneltypes, pt);
-
pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
strcpy(pt->idname, "VIEW3D_PT_last_operator");
strcpy(pt->label, "Last Operator");
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index b57f4a91004..2db5f2c97fd 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -76,12 +76,11 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "GPU_draw.h"
-
#include "PIL_time.h" /* smoothview */
#include "view3d_intern.h" // own include
+
/* use this call when executing an operator,
event system doesn't set for each event the
opengl drawing context */
@@ -1431,9 +1430,6 @@ static int game_engine_exec(bContext *C, wmOperator *unused)
Scene *startscene = CTX_data_scene(C);
#if GAMEBLENDER == 1
-
- view3d_operator_needs_opengl(C);
-
SaveState(C);
StartKetsjiShell(C, 1);
RestoreState(C);
diff --git a/source/blender/editors/transform/Makefile b/source/blender/editors/transform/Makefile
index 607038b413b..bc3e08a2ae8 100644
--- a/source/blender/editors/transform/Makefile
+++ b/source/blender/editors/transform/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 3311fb7d0fe..674de81a9f5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1134,7 +1134,7 @@ void drawTransform(const struct bContext *C, struct ARegion *ar, void *arg)
void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *sce = CTX_data_scene(C);
int constraint_axis[3] = {0, 0, 0};
int proportional = 0;
@@ -1195,8 +1195,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
// XXX If modal, save settings back in scene
if (t->flag & T_MODAL)
{
- ts->prop_mode = t->prop_mode;
- ts->proportional = proportional;
+ sce->prop_mode = t->prop_mode;
+ sce->proportional = proportional;
if(t->spacetype == SPACE_VIEW3D)
{
@@ -2359,7 +2359,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
}
else if (t->flag & T_EDIT) {
- if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
+ if(t->around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
VECCOPY(center, td->center);
}
else {
@@ -2660,7 +2660,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
}
else {
/* !TODO! Make this if not rely on G */
- if(around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
+ if(around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
center = td->center;
}
}
@@ -3126,7 +3126,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
sprintf(distvec, "%.4f", dist);
if(t->flag & T_AUTOIK) {
- short chainlen= t->settings->autoik_chainlen;
+ short chainlen= t->scene->toolsettings->autoik_chainlen;
if(chainlen)
sprintf(autoik, "AutoIK-Len: %d", chainlen);
@@ -4251,7 +4251,7 @@ int Align(TransInfo *t, short mval[2])
VECCOPY(t->center, td->center);
}
else {
- if(t->settings->selectmode & SCE_SELECT_FACE) {
+ if(t->scene->selectmode & SCE_SELECT_FACE) {
VECCOPY(t->center, td->center);
}
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 534f142734a..ee767fada58 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -257,7 +257,6 @@ typedef struct TransInfo {
struct ScrArea *sa;
struct ARegion *ar;
struct Scene *scene;
- struct ToolSettings *settings;
struct wmTimer *animtimer;
short mval[2]; /* current mouse position */
struct Object *obedit;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 490ce820b30..6c7aa1ee49d 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -777,7 +777,7 @@ static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
/* change the chain-length of auto-ik */
void transform_autoik_update (TransInfo *t, short mode)
{
- short *chainlen= &t->settings->autoik_chainlen;
+ short *chainlen= &t->scene->toolsettings->autoik_chainlen;
bPoseChannel *pchan;
/* mode determines what change to apply to chainlen */
@@ -1631,7 +1631,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
int count = 0, hasselected = 0;
int propmode = t->flag & T_PROP_EDIT;
- if(psys==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
+ if(psys==NULL || t->scene->selectmode==SCE_SELECT_PATH) return;
psmd = psys_get_modifier(ob,psys);
@@ -2101,7 +2101,7 @@ void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
static void createTransEditVerts(bContext *C, TransInfo *t)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
TransData *tob = NULL;
EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
EditVert *eve;
@@ -2119,7 +2119,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
// transform now requires awareness for select mode, so we tag the f1 flags in verts
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(scene->selectmode & SCE_SELECT_VERTEX) {
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && (eve->f & SELECT))
eve->f1= SELECT;
@@ -2127,7 +2127,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
eve->f1= 0;
}
}
- else if(ts->selectmode & SCE_SELECT_EDGE) {
+ else if(scene->selectmode & SCE_SELECT_EDGE) {
EditEdge *eed;
for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
for(eed= em->edges.first; eed; eed= eed->next) {
@@ -4672,14 +4672,8 @@ void special_aftertrans_update(TransInfo *t)
if (base->flag & SELECT && (t->mode != TFM_DUMMY)) {
/* pointcache refresh */
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
+ if (BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
ob->recalc |= OB_RECALC_DATA;
-
- /* Needed for proper updating of "quick cached" dynamics. */
- /* Creates troubles for moving animated objects without */
- /* autokey though, probably needed is an anim sys override? */
- /* Please remove if some other solution is found. -jahka */
- DAG_object_flush_update(scene, ob, OB_RECALC_OB);
/* Set autokey if necessary */
if (!cancelled)
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index e157d7f68f9..171665c9282 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -665,7 +665,6 @@ void resetTransRestrictions(TransInfo *t)
int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
{
Scene *sce = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
@@ -680,7 +679,6 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
t->sa = sa;
t->ar = ar;
t->obedit = obedit;
- t->settings = ts;
t->data = NULL;
t->ext = NULL;
@@ -754,10 +752,9 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
}
else if(t->spacetype==SPACE_IMAGE || t->spacetype==SPACE_NODE)
{
- SpaceImage *sima = sa->spacedata.first;
// XXX for now, get View2D from the active region
t->view = &ar->v2d;
- t->around = sima->around;
+ t->around = ar->v2d.around;
}
else
{
@@ -777,7 +774,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
// Need stuff to take it from edit mesh or whatnot here
else
{
- if (t->obedit && t->obedit->type == OB_MESH && ts->editbutflag & B_MESH_X_MIRROR)
+ if (t->obedit && t->obedit->type == OB_MESH && sce->toolsettings->editbutflag & B_MESH_X_MIRROR)
{
t->flag |= T_MIRROR;
}
@@ -797,10 +794,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
}
else
{
- if ((t->options & CTX_NO_PET) == 0 && (ts->proportional)) {
+ if ((t->options & CTX_NO_PET) == 0 && (sce->proportional)) {
t->flag |= T_PROP_EDIT;
- if(ts->proportional == 2)
+ if(sce->proportional == 2)
t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
}
}
@@ -811,7 +808,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
}
else
{
- t->prop_size = ts->proportional_size;
+ t->prop_size = sce->toolsettings->proportional_size;
}
if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
@@ -820,7 +817,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
}
else
{
- t->prop_mode = ts->prop_mode;
+ t->prop_mode = sce->prop_mode;
}
/* TRANSFORM_FIX_ME rna restrictions */
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 631eb1eb134..4d721a83c78 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: transform_input.c 18142 2008-12-29 07:19:16Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -26,7 +26,6 @@
#include <math.h>
#include "DNA_screen_types.h"
-#include "DNA_windowmanager_types.h"
#include "BLI_arithb.h"
diff --git a/source/blender/editors/transform/transform_ndofinput.c b/source/blender/editors/transform/transform_ndofinput.c
index 9c2a1a7db6d..c52492ebd6b 100644
--- a/source/blender/editors/transform/transform_ndofinput.c
+++ b/source/blender/editors/transform/transform_ndofinput.c
@@ -31,7 +31,6 @@
#include "BKE_utildefines.h" /* ABS */
#include "DNA_view3d_types.h" /* for G.vd (view3d) */
-#include "DNA_windowmanager_types.h" /* for G.vd (view3d) */
#include "WM_types.h"
diff --git a/source/blender/editors/transform/transform_numinput.c b/source/blender/editors/transform/transform_numinput.c
index f5f1d5fac9e..34976105db3 100644
--- a/source/blender/editors/transform/transform_numinput.c
+++ b/source/blender/editors/transform/transform_numinput.c
@@ -34,7 +34,6 @@
#include "BKE_utildefines.h" /* ABS */
#include "WM_types.h"
-#include "DNA_windowmanager_types.h"
#include "transform.h"
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 9e4115f38f0..e697b6dfa7d 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: transform_ops.c 17542 2008-11-23 15:27:53Z theeth $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 0b9a176dbdf..72901110388 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -210,7 +210,7 @@ int handleSnapping(TransInfo *t, wmEvent *event)
if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift)
{
/* toggle snap and reinit */
- t->settings->snap_flag ^= SCE_SNAP;
+ t->scene->snap_flag ^= SCE_SNAP;
initSnapping(t, NULL);
status = 1;
}
@@ -282,10 +282,10 @@ int validSnappingNormal(TransInfo *t)
void initSnapping(TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = t->settings;
+ Scene *scene = t->scene;
Object *obedit = t->obedit;
int snapping = 0;
- short snap_mode = t->settings->snap_target;
+ short snap_mode = t->scene->snap_target;
resetSnapping(t);
@@ -310,8 +310,8 @@ void initSnapping(TransInfo *t, wmOperator *op)
}
else
{
- snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP);
- t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
+ snapping = ((scene->snap_flag & SCE_SNAP) == SCE_SNAP);
+ t->tsnap.align = ((t->scene->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
}
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
@@ -542,7 +542,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
SnapMode mode;
- if (t->settings->snap_mode == SCE_SNAP_MODE_VOLUME)
+ if (t->scene->snap_mode == SCE_SNAP_MODE_VOLUME)
{
ListBase depth_peels;
DepthPeel *p1, *p2;
@@ -575,7 +575,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
p1->flag = 1;
/* if peeling objects, take the first and last from each object */
- if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT)
+ if (t->scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
{
DepthPeel *peel;
for (peel = p1->next; peel; peel = peel->next)
@@ -1346,7 +1346,6 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
{
- ToolSettings *ts= scene->toolsettings;
int retval = 0;
if (ob->type == OB_MESH) {
@@ -1364,13 +1363,13 @@ int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obma
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
}
- retval = snapDerivedMesh(ts->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+ retval = snapDerivedMesh(scene->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
dm->release(dm);
}
else if (ob->type == OB_ARMATURE)
{
- retval = snapArmature(ts->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+ retval = snapArmature(scene->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
}
return retval;
diff --git a/source/blender/editors/util/Makefile b/source/blender/editors/util/Makefile
index 303079daeee..da701dc5d86 100644
--- a/source/blender/editors/util/Makefile
+++ b/source/blender/editors/util/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 1d79c542fa9..62ce76a7614 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -183,8 +183,6 @@ void ED_undo_redo(bContext *C)
static int ed_undo_exec(bContext *C, wmOperator *op)
{
- /* "last operator" should disappear, later we can tie ths with undo stack nicer */
- WM_operator_stack_clear(C);
return ed_undo_step(C, 1);
}
static int ed_redo_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/uvedit/Makefile b/source/blender/editors/uvedit/Makefile
index d589bbec3bc..b8a8f0bc8af 100644
--- a/source/blender/editors/uvedit/Makefile
+++ b/source/blender/editors/uvedit/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index b811906f5e5..aded5a4cff9 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -102,19 +102,17 @@ static void drawcursor_sima(SpaceImage *sima, ARegion *ar)
static int draw_uvs_face_check(Scene *scene)
{
- ToolSettings *ts= scene->toolsettings;
-
/* checks if we are selecting only faces */
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
return 2;
- else if(ts->selectmode & SCE_SELECT_FACE)
+ else if(scene->selectmode & SCE_SELECT_FACE)
return 1;
else
return 0;
}
else
- return (ts->uv_selectmode == UV_SELECT_FACE);
+ return (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
}
static void draw_uvs_shadow(SpaceImage *sima, Object *obedit)
@@ -420,7 +418,7 @@ static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFac
/* draws uv's in the image space */
static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
{
- ToolSettings *ts;
+ ToolSettings *settings;
Mesh *me= obedit->data;
EditMesh *em;
EditFace *efa, *efa_act;
@@ -434,13 +432,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
em= BKE_mesh_get_editmesh(me);
activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */
- ts= scene->toolsettings;
+ settings= scene->toolsettings;
drawfaces= draw_uvs_face_check(scene);
- if(ts->uv_flag & UV_SYNC_SELECTION)
- interpedges= (ts->selectmode & SCE_SELECT_VERTEX);
+ if(settings->uv_flag & UV_SYNC_SELECTION)
+ interpedges= (scene->selectmode & SCE_SELECT_VERTEX);
else
- interpedges= (ts->uv_selectmode == UV_SELECT_VERTEX);
+ interpedges= (settings->uv_selectmode == UV_SELECT_VERTEX);
/* draw other uvs */
if(sima->flag & SI_DRAW_OTHER)
@@ -456,7 +454,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* when sync selection is enabled, all faces are drawn (except for hidden)
* so if cage is the same as the final, theres no point in drawing this */
- if(!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
+ if(!((settings->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
draw_uvs_dm_shadow(finaldm);
/* release derivedmesh again */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 7582145c63b..7dca4d34c48 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -191,9 +191,7 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
return (efa->h==0);
else
return (efa->h==0 && (efa->f & SELECT));
@@ -201,9 +199,7 @@ int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
+ if(scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)
return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0;
else
return uvedit_face_visible_nolocal(scene, efa);
@@ -211,9 +207,7 @@ int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
return (efa->f & SELECT);
else
return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
@@ -221,9 +215,7 @@ int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
EM_select_face(efa, 1);
else
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
@@ -231,9 +223,7 @@ void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
EM_select_face(efa, 0);
else
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
@@ -241,13 +231,12 @@ void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
int nvert= (efa->v4)? 4: 3;
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
return (efa->f & SELECT);
- else if(ts->selectmode == SCE_SELECT_EDGE)
+ else if(scene->selectmode == SCE_SELECT_EDGE)
return (*(&efa->e1 + i))->f & SELECT;
else
return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
@@ -258,13 +247,12 @@ int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
int nvert= (efa->v4)? 4: 3;
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
EM_select_face(efa, 1);
- else if(ts->selectmode == SCE_SELECT_EDGE)
+ else if(scene->selectmode == SCE_SELECT_EDGE)
EM_select_edge((*(&efa->e1 + i)), 1);
else {
(efa->v1 + i)->f |= SELECT;
@@ -277,13 +265,12 @@ void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
int nvert= (efa->v4)? 4: 3;
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
EM_select_face(efa, 0);
- else if(ts->selectmode == SCE_SELECT_EDGE)
+ else if(scene->selectmode == SCE_SELECT_EDGE)
EM_select_edge((*(&efa->e1 + i)), 0);
else {
(efa->v1 + i)->f &= ~SELECT;
@@ -296,10 +283,8 @@ void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
return (efa->f & SELECT);
else
return (*(&efa->v1 + i))->f & SELECT;
@@ -310,10 +295,8 @@ int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
EM_select_face(efa, 1);
else
(*(&efa->v1 + i))->f |= SELECT;
@@ -324,10 +307,8 @@ void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
{
- ToolSettings *ts= scene->toolsettings;
-
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode == SCE_SELECT_FACE)
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
EM_select_face(efa, 0);
else
(*(&efa->v1 + i))->f &= ~SELECT;
@@ -1308,7 +1289,6 @@ void UV_OT_stitch(wmOperatorType *ot)
static int select_inverse_exec(bContext *C, wmOperator *op)
{
Scene *scene;
- ToolSettings *ts;
Object *obedit;
EditMesh *em;
EditFace *efa;
@@ -1316,12 +1296,11 @@ static int select_inverse_exec(bContext *C, wmOperator *op)
MTFace *tf;
scene= CTX_data_scene(C);
- ts= CTX_data_tool_settings(C);
obedit= CTX_data_edit_object(C);
em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
ima= CTX_data_edit_image(C);
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
EM_select_swap(em);
}
else {
@@ -1360,7 +1339,6 @@ void UV_OT_select_invert(wmOperatorType *ot)
static int de_select_all_exec(bContext *C, wmOperator *op)
{
Scene *scene;
- ToolSettings *ts;
Object *obedit;
EditMesh *em;
EditFace *efa;
@@ -1369,12 +1347,11 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
int sel;
scene= CTX_data_scene(C);
- ts= CTX_data_tool_settings(C);
obedit= CTX_data_edit_object(C);
em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
ima= CTX_data_edit_image(C);
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
EM_toggle_select_all(em);
}
else {
@@ -1454,7 +1431,6 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
@@ -1469,12 +1445,12 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
uvedit_pixel_to_float(sima, penalty, 5.0f);
/* retrieve operation mode */
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
sync= 1;
- if(ts->selectmode & SCE_SELECT_FACE)
+ if(scene->selectmode & SCE_SELECT_FACE)
selectmode= UV_SELECT_FACE;
- else if(ts->selectmode & SCE_SELECT_EDGE)
+ else if(scene->selectmode & SCE_SELECT_EDGE)
selectmode= UV_SELECT_EDGE;
else
selectmode= UV_SELECT_VERTEX;
@@ -1483,7 +1459,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
}
else {
sync= 0;
- selectmode= ts->uv_selectmode;
+ selectmode= scene->toolsettings->uv_selectmode;
sticky= sima->sticky;
}
@@ -1705,7 +1681,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
if(sync) {
/* flush for mesh selection */
- if(ts->selectmode != SCE_SELECT_FACE) {
+ if(scene->selectmode != SCE_SELECT_FACE) {
if(flush==1) EM_select_flush(em);
else if(flush==-1) EM_deselect_flush(em);
}
@@ -1818,14 +1794,13 @@ static int select_linked_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
float limit[2];
int extend;
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
@@ -1863,14 +1838,13 @@ void UV_OT_select_linked(wmOperatorType *ot)
static int unlink_selection_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
EditFace *efa;
MTFace *tf;
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
@@ -1927,13 +1901,12 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
* This only needs to be done when the Mesh is not used for
* selection (so for sticky modes, vertex or location based). */
- ToolSettings *ts= CTX_data_tool_settings(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
EditFace *efa;
MTFace *tf;
int nverts, i;
- if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
+ if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
* in the loop and select all MTFace UV's that use a touched vert. */
EditVert *eve;
@@ -1964,7 +1937,7 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
}
}
}
- else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
+ else if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
EditFace *efa_vlist;
MTFace *tf_vlist;
UvMapVert *start_vlist=NULL, *vlist_iter;
@@ -2035,7 +2008,7 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
EM_free_uv_vert_map(vmap);
}
- else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
+ else { /* SI_STICKY_DISABLE or scene->toolsettings->uv_flag & UV_SYNC_SELECTION */
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->tmp.l) {
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
@@ -2053,7 +2026,6 @@ static int border_select_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
Scene *scene= CTX_data_scene(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
ARegion *ar= CTX_wm_region(C);
@@ -2077,10 +2049,10 @@ static int border_select_exec(bContext *C, wmOperator *op)
select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
pinned= RNA_boolean_get(op->ptr, "pinned");
- if(ts->uv_flag & UV_SYNC_SELECTION)
- faces= (ts->selectmode == SCE_SELECT_FACE);
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ faces= (scene->selectmode == SCE_SELECT_FACE);
else
- faces= (ts->uv_selectmode == UV_SELECT_FACE);
+ faces= (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
/* do actual selection */
if(faces && !pinned) {
@@ -2112,7 +2084,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
for(efa= em->faces.first; efa; efa= efa->next) {
tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
+ if(!pinned || (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) ) {
/* UV_SYNC_SELECTION - can't do pinned selection */
if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
if(select) uvedit_uv_select(scene, efa, tface, 0);
@@ -2161,8 +2133,8 @@ static int border_select_exec(bContext *C, wmOperator *op)
if(change) {
/* make sure newly selected vert selection is updated*/
- if(ts->uv_flag & UV_SYNC_SELECTION) {
- if(ts->selectmode != SCE_SELECT_FACE) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode != SCE_SELECT_FACE) {
if(select) EM_select_flush(em);
else EM_deselect_flush(em);
}
@@ -2696,14 +2668,14 @@ void UV_OT_select_pinned(wmOperatorType *ot)
static int hide_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
EditFace *efa;
MTFace *tf;
int swap= RNA_boolean_get(op->ptr, "unselected");
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
EM_hide_mesh(em, swap);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
@@ -2839,14 +2811,14 @@ void UV_OT_hide(wmOperatorType *ot)
static int reveal_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
+ Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
EditFace *efa;
MTFace *tf;
/* call the mesh function if we are in mesh sync sel */
- if(ts->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
EM_reveal_mesh(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile
index 3a3ac20ff6c..733ee3f764c 100644
--- a/source/blender/gpu/intern/Makefile
+++ b/source/blender/gpu/intern/Makefile
@@ -35,7 +35,7 @@ DIR = $(OCGDIR)/blender/$(LIBNAME)
include nan_compile.mk
-ifeq ($(OS),$(findstring $(OS), "darwin freebsd linux openbsd solaris windows"))
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
CFLAGS += -funsigned-char
endif
diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h
index 7b5d668ce2b..bd2a0d3082f 100644
--- a/source/blender/imbuf/intern/imbuf.h
+++ b/source/blender/imbuf/intern/imbuf.h
@@ -51,7 +51,7 @@
#include <sys/mman.h>
#endif
-#if !defined(WIN32)
+#if !defined(WIN32) && !defined(__BeOS)
#define O_BINARY 0
#endif
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 1a6ab104bcf..6df92f69fff 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -244,6 +244,26 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
size = BLI_filesize(file);
+#if defined(AMIGA) || defined(__BeOS)
+ mem= (int *)malloc(size);
+ if (mem==0) {
+ printf("Out of mem\n");
+ return (0);
+ }
+
+ if (read(file, mem, size)!=size){
+ printf("Read Error\n");
+ free(mem);
+ return (0);
+ }
+
+ ibuf = IMB_ibImageFromMemory(mem, size, flags);
+ free(mem);
+
+ /* for jpeg read */
+ lseek(file, 0L, SEEK_SET);
+
+#else
mem= (int *)mmap(0,size,PROT_READ,MAP_SHARED,file,0);
if (mem==(int *)-1){
printf("Couldn't get mapping\n");
@@ -255,6 +275,7 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
if (munmap( (void *) mem, size)){
printf("Couldn't unmap file.\n");
}
+#endif
return(ibuf);
}
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 88d9894cf7a..718d1a17834 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -33,8 +33,6 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-#include "DNA_listBase.h"
typedef struct PartDeflect {
short deflect; /* Deflection flag - does mesh deflect particles*/
@@ -74,26 +72,12 @@ typedef struct PartDeflect {
int seed; /* wind noise random seed */
} PartDeflect;
-typedef struct PTCacheMem {
- struct PTCacheMem *next, *prev;
- int frame, totpoint;
- float *data; /* data points */
- void *xdata; /* extra data */
-} PTCacheMem;
-
typedef struct PointCache {
int flag; /* generic flag */
- int step; /* frames between cached frames */
int simframe; /* current frame of simulation (only if SIMULATION_VALID) */
int startframe; /* simulation start frame */
int endframe; /* simulation end frame */
int editframe; /* frame being edited (runtime only) */
- int last_exact; /* last exact frame that's cached */
- int xdata_type; /* type of extra data */
- char name[64];
- char prev_name[64];
- char info[64];
- struct ListBase mem_cache;
} PointCache;
typedef struct SBVertex {
@@ -263,12 +247,6 @@ typedef struct SoftBody {
#define PTCACHE_BAKING 8
#define PTCACHE_BAKE_EDIT 16
#define PTCACHE_BAKE_EDIT_ACTIVE 32
-#define PTCACHE_DISK_CACHE 64
-#define PTCACHE_QUICK_CACHE 128
-#define PTCACHE_FRAMES_SKIPPED 256
-
-/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
-#define PTCACHE_REDO_NEEDED 258
/* ob->softflag */
#define OB_SB_ENABLE 1
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 05f1cc1f351..6805082d094 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -34,8 +34,6 @@
#include "DNA_ID.h"
-struct AnimData;
-
typedef struct HairKey {
float co[3]; /* location of hair vertex */
float time; /* time along hair, default 0-100 */
@@ -102,7 +100,6 @@ typedef struct ParticleData {
typedef struct ParticleSettings {
ID id;
- struct AnimData *adt;
int flag;
short type, from, distr;
@@ -170,7 +167,7 @@ typedef struct ParticleSettings {
struct Group *eff_group;
struct Object *dup_ob;
struct Object *bb_ob;
- struct Ipo *ipo; // xxx depreceated... old animation system
+ struct Ipo *ipo;
struct PartDeflect *pd;
struct PartDeflect *pd2;
} ParticleSettings;
@@ -195,7 +192,6 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
struct Object *target_ob;
struct Object *keyed_ob;
struct Object *lattice;
- struct Object *parent; /* particles from global space -> parent space */
struct ListBase effectors, reactevents; /* runtime */
diff --git a/source/blender/makesdna/DNA_radio_types.h b/source/blender/makesdna/DNA_radio_types.h
new file mode 100644
index 00000000000..4219bf59b93
--- /dev/null
+++ b/source/blender/makesdna/DNA_radio_types.h
@@ -0,0 +1,62 @@
+/**
+ * radio_types.h dec 2000 Nzc
+ *
+ * All type defs for the Blender core.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef DNA_RADIO_TYPES_H
+#define DNA_RADIO_TYPES_H
+
+typedef struct Radio {
+ short hemires, maxiter;
+ short drawtype, flag; /* bit 0 and 1: show limits */
+ short subshootp, subshoote, nodelim, maxsublamp;
+ short pama, pami, elma, elmi; /* patch and elem limits */
+ int maxnode;
+ float convergence;
+ float radfac, gamma; /* for display */
+
+} Radio;
+
+
+/* **************** RADIOSITY ********************* */
+
+/* draw type */
+#define RAD_WIREFRAME 0
+#define RAD_SOLID 1
+#define RAD_GOURAUD 2
+
+/* flag */
+#define RAD_SHOWLIMITS 1
+#define RAD_SHOWZ 2
+
+#endif
+
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 9a3ef758bd3..e8279604100 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -39,6 +39,7 @@ extern "C" {
#include "DNA_scriptlink_types.h"
#include "DNA_ID.h"
+struct Radio;
struct Object;
struct World;
struct Scene;
@@ -47,7 +48,6 @@ struct Group;
struct Text;
struct bNodeTree;
struct AnimData;
-struct Editing;
typedef struct Base {
struct Base *next, *prev;
@@ -158,7 +158,7 @@ typedef struct SceneRenderLayer {
#define SCE_PASS_REFRACT 1024
#define SCE_PASS_INDEXOB 2048
#define SCE_PASS_UV 4096
-#define SCE_PASS_RADIO 8192 /* Radio removed, can use for new GI? */
+#define SCE_PASS_RADIO 8192
#define SCE_PASS_MIST 16384
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */
@@ -385,8 +385,6 @@ typedef struct ParticleEditSettings {
float emitterdist;
int draw_timed;
-
- int selectmode, pad;
} ParticleEditSettings;
typedef struct TransformOrientation {
@@ -446,19 +444,14 @@ typedef struct ToolSettings {
short editbutflag;
/*Triangle to Quad conversion threshold*/
float jointrilimit;
- /* Editmode Tools */
+ /* Extrude Tools */
float degr;
short step;
short turn;
- float extr_offs; /* extrude offset */
- float doublimit; /* remove doubles limit */
- float normalsize; /* size of normals */
- short automerge;
-
- /* Selection Mode for Mesh */
- short selectmode;
-
+ float extr_offs;
+ float doublimit;
+
/* Primitive Settings */
/* UV Sphere */
short segments;
@@ -494,11 +487,8 @@ typedef struct ToolSettings {
/* Select Group Threshold */
float select_thresh;
- /* Graph Editor */
+ /* IPO-Editor */
float clean_thresh;
-
- /* Auto-Keying Mode */
- short autokey_mode, pad2; /* defines in DNA_userdef_types.h */
/* Retopo */
char retopo_mode;
@@ -525,6 +515,7 @@ typedef struct ToolSettings {
char skgen_postpro_passes;
char skgen_subdivisions[3];
char skgen_multi_level;
+ int skgen_pad;
/* Skeleton Sketching */
struct Object *skgen_template;
@@ -538,10 +529,7 @@ typedef struct ToolSettings {
/* Alt+RMB option */
char edge_mode;
-
- /* transform */
- short snap_mode, snap_flag, snap_target;
- short proportional, prop_mode;
+ char pad3[2];
} ToolSettings;
typedef struct bStats {
@@ -562,22 +550,29 @@ typedef struct Scene {
struct Image *ima;
ListBase base;
- struct Base *basact; /* active base */
+ struct Base *basact;
struct Object *obedit; /* name replaces old G.obedit */
- float cursor[3]; /* 3d cursor location */
+ float cursor[3];
float twcent[3]; /* center for transform widget */
float twmin[3], twmax[3]; /* boundbox of selection for transform widget */
unsigned int lay;
+ /* editmode stuff */
+ float editbutsize; /* size of normals */
+ short selectmode; /* for mesh only! */
+ short proportional, prop_mode;
+ short automerge, pad5;
short flag; /* various settings */
+ short autokey_mode; /* mode for autokeying (defines in DNA_userdef_types.h) */
short use_nodes;
struct bNodeTree *nodetree;
- struct Editing *ed; /* sequence editor data is allocated here */
+ void *ed; /* sequence editor data is allocated here */
+ struct Radio *radio;
struct GameFraming framing;
@@ -587,20 +582,20 @@ typedef struct Scene {
/* migrate or replace? depends on some internal things... */
/* no, is on the right place (ton) */
struct RenderData r;
- struct AudioData audio; /* DEPRECATED 2.5 */
+ struct AudioData audio; /* DEPRICATED 2.5 */
ScriptLink scriptlink;
ListBase markers;
ListBase transform_spaces;
+ short jumpframe;
+ short snap_mode, snap_flag, snap_target;
/* none of the dependancy graph vars is mean to be saved */
struct DagForest *theDag;
short dagisvalid, dagflags;
- short recalc; /* recalc = counterpart of ob->recalc */
-
- short jumpframe;
+ short pad4, recalc; /* recalc = counterpart of ob->recalc */
/* frame step. */
int frame_step;
@@ -806,27 +801,27 @@ typedef struct Scene {
/* base->flag is in DNA_object_types.h */
-/* toolsettings->snap_flag */
+/* scene->snap_flag */
#define SCE_SNAP 1
#define SCE_SNAP_ROTATE 2
#define SCE_SNAP_PEEL_OBJECT 4
-/* toolsettings->snap_target */
+/* scene->snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1
#define SCE_SNAP_TARGET_MEDIAN 2
#define SCE_SNAP_TARGET_ACTIVE 3
-/* toolsettings->snap_mode */
+/* scene->snap_mode */
#define SCE_SNAP_MODE_VERTEX 0
#define SCE_SNAP_MODE_EDGE 1
#define SCE_SNAP_MODE_FACE 2
#define SCE_SNAP_MODE_VOLUME 3
-/* toolsettings->selectmode */
+/* sce->selectmode */
#define SCE_SELECT_VERTEX 1 /* for mesh */
#define SCE_SELECT_EDGE 2
#define SCE_SELECT_FACE 4
-/* toolsettings->particle.selectmode for particles */
+/* sce->selectmode for particles */
#define SCE_SELECT_PATH 1
#define SCE_SELECT_POINT 2
#define SCE_SELECT_END 4
@@ -834,7 +829,7 @@ typedef struct Scene {
/* sce->recalc (now in use by previewrender) */
#define SCE_PRV_CHANGED 1
-/* toolsettings->prop_mode (proportional falloff) */
+/* sce->prop_mode (proportional falloff) */
#define PROP_SMOOTH 0
#define PROP_SPHERE 1
#define PROP_ROOT 2
@@ -901,7 +896,7 @@ typedef enum SculptFlags {
/* toolsettings->uv_selectmode */
#define UV_SELECT_VERTEX 1
-#define UV_SELECT_EDGE 2
+#define UV_SELECT_EDGE 2 /* not implemented */
#define UV_SELECT_FACE 4
#define UV_SELECT_ISLAND 8
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 9dc7e07a95c..416acd7467e 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -229,7 +229,7 @@ typedef struct SpaceImage {
char dt_uv; /* UV draw type */
char sticky; /* sticky selection type */
char dt_uvstretch;
- char around;
+ char pad;
float xof, yof; /* user defined offset, image is centered */
float zoom, pad4; /* user defined zoom level */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 771a7e43793..9d554c88a95 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -67,8 +67,7 @@ typedef struct uiFontStyle {
short uifont_id; /* saved in file, 0 is default */
short points; /* actual size depends on 'global' dpi */
float kerning; /* kerning space between characters. */
- short overlap; /* check overlaped characters. */
- short pad;
+ float pad;
short italic, bold; /* style hint */
short shadow; /* value is amount of pixels blur */
short shadx, shady; /* shadow offset in pixels */
@@ -124,11 +123,10 @@ typedef struct uiWidgetColors {
typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
- uiWidgetColors wcol_regular, wcol_tool, wcol_text;
- uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
+ uiWidgetColors wcol_regular, wcol_tool, wcol_radio, wcol_text, wcol_option;
uiWidgetColors wcol_num, wcol_numslider;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item;
- uiWidgetColors wcol_box, wcol_scroll;
+ uiWidgetColors wcol_box;
char iconfile[80]; // FILE_MAXFILE length
@@ -381,7 +379,7 @@ extern UserDef U; /* from blenkernel blender.c */
#define USER_ZOOM_TO_MOUSEPOS (1 << 20)
#define USER_SHOW_FPS (1 << 21)
#define USER_MMB_PASTE (1 << 22)
-#define USER_MENUFIXEDORDER (1 << 23)
+#define USER_DIRECTIONALORDER (1 << 23)
/* Auto-Keying mode */
/* AUTOKEY_ON is a bitflag */
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index e02d2984771..7d6b5ec8764 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -222,36 +222,5 @@ typedef enum wmRadialControlMode {
WM_RADIALCONTROL_ANGLE
} wmRadialControlMode;
-/* ************** wmEvent ************************ */
-/* for read-only rna access, dont save this */
-
-/* each event should have full modifier state */
-/* event comes from eventmanager and from keymap */
-typedef struct wmEvent {
- struct wmEvent *next, *prev;
-
- short type; /* event code itself (short, is also in keymap) */
- short val; /* press, release, scrollvalue */
- short x, y; /* mouse pointer position, screen coord */
- short mval[2]; /* region mouse position, name convention pre 2.5 :) */
- short prevx, prevy; /* previous mouse pointer position */
- short unicode; /* future, ghost? */
- char ascii; /* from ghost */
- char pad;
-
- /* modifier states */
- short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */
- short keymodifier; /* rawkey modifier */
-
- /* keymap item, set by handler (weak?) */
- const char *keymap_idname;
-
- /* custom data */
- short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */
- void *customdata; /* ascii, unicode, mouse coords, angles, vectors, dragdrop info */
- short customdatafree;
-
-} wmEvent;
-
#endif /* DNA_WINDOWMANAGER_TYPES_H */
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 91e9e617ea9..bf2f0f3900e 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -98,6 +98,7 @@ char *includefiles[] = {
"DNA_object_force.h",
"DNA_object_fluidsim.h",
"DNA_world_types.h",
+ "DNA_radio_types.h",
"DNA_scene_types.h",
"DNA_view3d_types.h",
"DNA_view2d_types.h",
@@ -1123,6 +1124,7 @@ int main(int argc, char ** argv)
#include "DNA_object_force.h"
#include "DNA_object_fluidsim.h"
#include "DNA_world_types.h"
+#include "DNA_radio_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "DNA_view2d_types.h"
diff --git a/source/blender/makesrna/Makefile b/source/blender/makesrna/Makefile
index bed3e85550d..25625af57a6 100644
--- a/source/blender/makesrna/Makefile
+++ b/source/blender/makesrna/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 21247 2009-06-29 21:50:53Z jaguarandi $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 1f856062533..c1a659fee9b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: RNA_access.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -172,7 +172,6 @@ extern StructRNA RNA_EnvironmentMap;
extern StructRNA RNA_EnvironmentMapTexture;
extern StructRNA RNA_ExplodeModifier;
extern StructRNA RNA_ExpressionController;
-extern StructRNA RNA_Event;
extern StructRNA RNA_FCurve;
extern StructRNA RNA_FModifier;
extern StructRNA RNA_FModifierCycles;
@@ -514,8 +513,6 @@ const struct ListBase *RNA_struct_defined_properties(StructRNA *srna);
FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier);
const struct ListBase *RNA_struct_defined_functions(StructRNA *srna);
-char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen);
-
/* Properties
*
* Access to struct properties. All this works with RNA pointers rather than
@@ -544,9 +541,6 @@ void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin,
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax);
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision);
-int RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **identifier);
-int RNA_enum_name(const EnumPropertyItem *item, const int value, const char **name);
-
void RNA_property_enum_items(PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **item, int *totitem);
int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value);
int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
@@ -600,11 +594,6 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop);
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr);
int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr);
-/* efficient functions to set properties for arrays */
-int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array);
-int RNA_property_collection_raw_get(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len);
-int RNA_property_collection_raw_set(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len);
-
/* to create ID property groups */
void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop);
@@ -700,28 +689,6 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
RNA_property_collection_end(&rna_macro_iter); \
}
-#define RNA_PROP_BEGIN(sptr, itemptr, prop) \
- { \
- CollectionPropertyIterator rna_macro_iter; \
- for(RNA_property_collection_begin(sptr, prop, &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { \
- PointerRNA itemptr= rna_macro_iter.ptr;
-
-#define RNA_PROP_END \
- } \
- RNA_property_collection_end(&rna_macro_iter); \
- }
-
-#define RNA_STRUCT_BEGIN(sptr, prop) \
- { \
- CollectionPropertyIterator rna_macro_iter; \
- for(RNA_property_collection_begin(sptr, RNA_struct_iterator_property(sptr->type), &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { \
- PropertyRNA *prop= rna_macro_iter.ptr.data;
-
-#define RNA_STRUCT_END \
- } \
- RNA_property_collection_end(&rna_macro_iter); \
- }
-
/* check if the idproperty exists, for operators */
int RNA_property_is_set(PointerRNA *ptr, const char *name);
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 85a148be2e2..91669616d89 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: RNA_define.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -80,7 +80,7 @@ PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont, const char *identifier, c
PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
-PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
+PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 276f421c586..841b397f276 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: RNA_enum_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -40,9 +40,6 @@ extern EnumPropertyItem beztriple_interpolation_mode_items[];
extern EnumPropertyItem fmodifier_type_items[];
-extern EnumPropertyItem event_value_items[];
-extern EnumPropertyItem event_type_items[];
-
#endif /* RNA_ENUM_TYPES */
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 923191cba78..a0fa2cc3344 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: RNA_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -110,9 +110,7 @@ typedef enum PropertyFlag {
PROP_BUILTIN = 128,
PROP_EXPORT = 256,
PROP_RUNTIME = 512,
- PROP_IDPROPERTY = 1024,
- PROP_RAW_ACCESS = 8192,
- PROP_RAW_ARRAY = 16384,
+ PROP_IDPROPERTY = 1024
} PropertyFlag;
typedef struct CollectionPropertyIterator {
@@ -134,21 +132,6 @@ typedef struct CollectionPointerLink {
PointerRNA ptr;
} CollectionPointerLink;
-typedef enum RawPropertyType {
- PROP_RAW_CHAR,
- PROP_RAW_SHORT,
- PROP_RAW_INT,
- PROP_RAW_FLOAT,
- PROP_RAW_DOUBLE
-} RawPropertyType;
-
-typedef struct RawArray {
- void *array;
- RawPropertyType type;
- int len;
- int stride;
-} RawArray;
-
/* Iterator Utility */
typedef struct EnumPropertyItem {
diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile
index 1694e55ed4c..03f75f0bea6 100644
--- a/source/blender/makesrna/intern/Makefile
+++ b/source/blender/makesrna/intern/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 13161 2008-01-07 19:13:47Z hos $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index c42bc866f99..1db61a842e5 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: makesrna.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -36,7 +36,7 @@
#include "rna_internal.h"
-#define RNA_VERSION_DATE "$Id$"
+#define RNA_VERSION_DATE "$Id: makesrna.c 21247 2009-06-29 21:50:53Z jaguarandi $"
#ifdef _WIN32
#ifndef snprintf
@@ -248,7 +248,8 @@ static const char *rna_parameter_type_name(PropertyRNA *parm)
return rna_find_dna_type((const char *)pparm->type);
}
case PROP_COLLECTION: {
- return "ListBase";
+ CollectionPropertyRNA *cparm= (CollectionPropertyRNA*)parm;
+ return rna_find_dna_type((const char *)cparm->type);
}
default:
return "<error, no type specified>";
@@ -762,42 +763,6 @@ static char *rna_def_property_end_func(FILE *f, StructRNA *srna, PropertyRNA *pr
return func;
}
-static void rna_set_raw_property(PropertyDefRNA *dp, PropertyRNA *prop)
-{
- if(dp->dnapointerlevel != 0)
- return;
- if(!dp->dnatype || !dp->dnaname || !dp->dnastructname)
- return;
-
- if(strcmp(dp->dnatype, "char") == 0) {
- prop->rawtype= PROP_RAW_CHAR;
- prop->flag |= PROP_RAW_ACCESS;
- }
- else if(strcmp(dp->dnatype, "short") == 0) {
- prop->rawtype= PROP_RAW_SHORT;
- prop->flag |= PROP_RAW_ACCESS;
- }
- else if(strcmp(dp->dnatype, "int") == 0) {
- prop->rawtype= PROP_RAW_INT;
- prop->flag |= PROP_RAW_ACCESS;
- }
- else if(strcmp(dp->dnatype, "float") == 0) {
- prop->rawtype= PROP_RAW_FLOAT;
- prop->flag |= PROP_RAW_ACCESS;
- }
- else if(strcmp(dp->dnatype, "double") == 0) {
- prop->rawtype= PROP_RAW_DOUBLE;
- prop->flag |= PROP_RAW_ACCESS;
- }
-}
-
-static void rna_set_raw_offset(FILE *f, StructRNA *srna, PropertyRNA *prop)
-{
- PropertyDefRNA *dp= rna_find_struct_property_def(srna, prop);
-
- fprintf(f, "\toffsetof(%s, %s), %d", dp->dnastructname, dp->dnaname, prop->rawtype);
-}
-
static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
{
PropertyRNA *prop;
@@ -809,9 +774,6 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
if(!prop->arraylength) {
- if(!bprop->get && !bprop->set && !dp->booleanbit)
- rna_set_raw_property(dp, prop);
-
bprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)bprop->get);
bprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)bprop->set);
}
@@ -825,16 +787,10 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
if(!prop->arraylength) {
- if(!iprop->get && !iprop->set)
- rna_set_raw_property(dp, prop);
-
iprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->get);
iprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->set);
}
else {
- if(!iprop->getarray && !iprop->setarray)
- rna_set_raw_property(dp, prop);
-
iprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->getarray);
iprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->setarray);
}
@@ -844,16 +800,10 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
if(!prop->arraylength) {
- if(!fprop->get && !fprop->set)
- rna_set_raw_property(dp, prop);
-
fprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->get);
fprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->set);
}
else {
- if(!fprop->getarray && !fprop->setarray)
- rna_set_raw_property(dp, prop);
-
fprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->getarray);
fprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->setarray);
}
@@ -892,13 +842,6 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
else if(dp->dnalengthname || dp->dnalengthfixed)
cprop->length= (void*)rna_def_property_length_func(f, srna, prop, dp, (char*)cprop->length);
- /* test if we can allow raw array access, if it is using our standard
- * array get/next function, we can be sure it is an actual array */
- if(cprop->next && cprop->get)
- if(strcmp((char*)cprop->next, "rna_iterator_array_next") == 0 &&
- strcmp((char*)cprop->get, "rna_iterator_array_get") == 0)
- prop->flag |= PROP_RAW_ARRAY;
-
cprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)cprop->get);
cprop->begin= (void*)rna_def_property_begin_func(f, srna, prop, dp, (char*)cprop->begin);
cprop->next= (void*)rna_def_property_next_func(f, srna, prop, dp, (char*)cprop->next);
@@ -1173,11 +1116,9 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
funcname= rna_alloc_function_name(srna->identifier, func->identifier, "call");
- /* function definition */
fprintf(f, "void %s(bContext *C, ReportList *reports, PointerRNA *_ptr, ParameterList *_parms)", funcname);
fprintf(f, "\n{\n");
- /* variable definitions */
if((func->flag & FUNC_NO_SELF)==0) {
if(dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname);
else fprintf(f, "\tstruct %s *_self;\n", srna->identifier);
@@ -1194,7 +1135,6 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
fprintf(f, ";\n");
fprintf(f, "\t\n");
- /* assign self */
if((func->flag & FUNC_NO_SELF)==0) {
if(dsrna->dnaname) fprintf(f, "\t_self= (struct %s *)_ptr->data;\n", dsrna->dnaname);
else fprintf(f, "\t_self= (struct %s *)_ptr->data;\n", srna->identifier);
@@ -1465,7 +1405,6 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
dsrna= rna_find_struct_def(srna);
func= dfunc->func;
- /* return type */
for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) {
if(dparm->prop==func->ret) {
if(dparm->prop->arraylength)
@@ -1479,16 +1418,13 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
}
}
- /* void if nothing to return */
if(!dparm)
fprintf(f, "void ");
- /* function name */
fprintf(f, "%s(", dfunc->call);
first= 1;
- /* self, context and reports parameters */
if((func->flag & FUNC_NO_SELF)==0) {
if(dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname);
else fprintf(f, "struct %s *_self", srna->identifier);
@@ -1507,7 +1443,6 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
fprintf(f, "ReportList *reports");
}
- /* defined parameters */
for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) {
if(dparm->prop==func->ret)
continue;
@@ -1596,7 +1531,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
DefRNA.error= 1;
}
break;
- }
+ }
case PROP_BOOLEAN: {
BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
unsigned int i;
@@ -1616,7 +1551,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
fprintf(f, "};\n\n");
}
break;
- }
+ }
case PROP_INT: {
IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
unsigned int i;
@@ -1636,7 +1571,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
fprintf(f, "};\n\n");
}
break;
- }
+ }
case PROP_FLOAT: {
FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
unsigned int i;
@@ -1656,7 +1591,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
fprintf(f, "};\n\n");
}
break;
- }
+ }
default:
break;
}
@@ -1671,14 +1606,10 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_print_c_string(f, prop->identifier);
fprintf(f, ", %d, ", prop->flag);
rna_print_c_string(f, prop->name); fprintf(f, ",\n\t");
- rna_print_c_string(f, prop->description); fprintf(f, ",\n\t");
- fprintf(f, "%d,\n", prop->icon);
+ rna_print_c_string(f, prop->description); fprintf(f, ",\n");
+ fprintf(f, "%d, ", prop->icon);
fprintf(f, "\t%s, %s, %d,\n", rna_property_typename(prop->type), rna_property_subtypename(prop->subtype), prop->arraylength);
- fprintf(f, "\t%s, %d, %s,\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable));
-
- if(prop->flag & PROP_RAW_ACCESS) rna_set_raw_offset(f, srna, prop);
- else fprintf(f, "\t0, 0");
- fprintf(f, "},\n");
+ fprintf(f, "\t%s, %d, %s},\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable));
switch(prop->type) {
case PROP_BOOLEAN: {
@@ -1687,7 +1618,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
else fprintf(f, "NULL\n");
break;
- }
+ }
case PROP_INT: {
IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, %s, %s,\n\t", rna_function_string(iprop->get), rna_function_string(iprop->set), rna_function_string(iprop->getarray), rna_function_string(iprop->setarray), rna_function_string(iprop->range));
@@ -1700,7 +1631,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
else fprintf(f, "NULL\n");
break;
- }
+ }
case PROP_FLOAT: {
FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, %s, %s, ", rna_function_string(fprop->get), rna_function_string(fprop->set), rna_function_string(fprop->getarray), rna_function_string(fprop->setarray), rna_function_string(fprop->range));
@@ -1714,13 +1645,13 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
else fprintf(f, "NULL\n");
break;
- }
+ }
case PROP_STRING: {
StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, %d, ", rna_function_string(sprop->get), rna_function_string(sprop->length), rna_function_string(sprop->set), sprop->maxlength);
rna_print_c_string(f, sprop->defaultvalue); fprintf(f, "\n");
break;
- }
+ }
case PROP_ENUM: {
EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, ", rna_function_string(eprop->get), rna_function_string(eprop->set), rna_function_string(eprop->itemf));
@@ -1730,14 +1661,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
fprintf(f, "NULL, ");
fprintf(f, "%d, %d\n", eprop->totitem, eprop->defaultvalue);
break;
- }
+ }
case PROP_POINTER: {
PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, ", rna_function_string(pprop->get), rna_function_string(pprop->set), rna_function_string(pprop->typef));
if(pprop->type) fprintf(f, "&RNA_%s\n", (char*)pprop->type);
else fprintf(f, "NULL\n");
break;
- }
+ }
case PROP_COLLECTION: {
CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, ", rna_function_string(cprop->begin), rna_function_string(cprop->next), rna_function_string(cprop->end), rna_function_string(cprop->get), rna_function_string(cprop->length), rna_function_string(cprop->lookupint), rna_function_string(cprop->lookupstring));
@@ -1922,6 +1853,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
{"rna_particle.c", NULL, RNA_def_particle},
{"rna_pose.c", NULL, RNA_def_pose},
{"rna_property.c", NULL, RNA_def_gameproperty},
+ {"rna_radio.c", NULL, RNA_def_radio},
{"rna_scene.c", NULL, RNA_def_scene},
{"rna_screen.c", NULL, RNA_def_screen},
{"rna_scriptlink.c", NULL, RNA_def_scriptlink},
@@ -1952,7 +1884,6 @@ static void rna_generate(BlenderRNA *brna, FILE *f, char *filename, char *api_fi
fprintf(f, "#include <float.h>\n");
fprintf(f, "#include <limits.h>\n");
fprintf(f, "#include <string.h>\n\n");
- fprintf(f, "#include <stddef.h>\n\n");
fprintf(f, "#include \"DNA_ID.h\"\n");
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 7d8bab8bee8..e70cd6ff8d3 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_ID.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index d3e4780c7fd..3073029d9b4 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_access.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -426,16 +426,23 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
/* Find the property which uses the given nested struct */
PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
{
- PropertyRNA *prop= NULL;
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *prop;
+ int i = 0;
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+ prop= NULL;
- RNA_STRUCT_BEGIN(ptr, iprop) {
+ for(; iter.valid; RNA_property_collection_next(&iter), i++) {
/* This assumes that there can only be one user of this nested struct */
- if (RNA_property_pointer_type(ptr, iprop) == srna) {
- prop= iprop;
+ if (RNA_property_pointer_type(ptr, iter.ptr.data) == srna) {
+ prop= iter.ptr.data;
break;
}
}
- RNA_PROP_END;
+
+ RNA_property_collection_end(&iter);
return prop;
}
@@ -448,21 +455,25 @@ const struct ListBase *RNA_struct_defined_properties(StructRNA *srna)
FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier)
{
PointerRNA tptr;
+ CollectionPropertyIterator iter;
PropertyRNA *iterprop;
FunctionRNA *func;
+ int i = 0;
RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr);
iterprop= RNA_struct_find_property(&tptr, "functions");
+ RNA_property_collection_begin(&tptr, iterprop, &iter);
func= NULL;
- RNA_PROP_BEGIN(&tptr, funcptr, iterprop) {
- if(strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
- func= funcptr.data;
+ for(; iter.valid; RNA_property_collection_next(&iter), i++) {
+ if(strcmp(identifier, RNA_function_identifier(iter.ptr.data)) == 0) {
+ func= iter.ptr.data;
break;
}
}
- RNA_PROP_END;
+
+ RNA_property_collection_end(&iter);
return func;
}
@@ -507,16 +518,6 @@ void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
srna->blender_type= blender_type;
}
-char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen)
-{
- PropertyRNA *nameprop;
-
- if(ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
- return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen);
-
- return NULL;
-}
-
/* Property Information */
const char *RNA_property_identifier(PropertyRNA *prop)
@@ -642,27 +643,25 @@ void RNA_property_enum_items(PointerRNA *ptr, PropertyRNA *prop, const EnumPrope
if(eprop->itemf) {
*item= eprop->itemf(ptr);
- if(totitem) {
- for(tot=0; (*item)[tot].identifier; tot++);
- *totitem= tot;
- }
+ for(tot=0; (*item)[tot].identifier; tot++);
+ *totitem= tot;
}
else {
*item= eprop->item;
- if(totitem)
- *totitem= eprop->totitem;
+ *totitem= eprop->totitem;
}
}
int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
{
const EnumPropertyItem *item;
+ int totitem, i;
- RNA_property_enum_items(ptr, prop, &item, NULL);
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
- for(; item->identifier; item++) {
- if(strcmp(item->identifier, identifier)==0) {
- *value = item->value;
+ for(i=0; i<totitem; i++) {
+ if(strcmp(item[i].identifier, identifier)==0) {
+ *value = item[i].value;
return 1;
}
}
@@ -670,34 +669,21 @@ int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *iden
return 0;
}
-int RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **identifier)
-{
- for (; item->identifier; item++) {
- if(item->value==value) {
- *identifier = item->identifier;
- return 1;
- }
- }
- return 0;
-}
-
-int RNA_enum_name(const EnumPropertyItem *item, const int value, const char **name)
-{
- for (; item->identifier; item++) {
- if(item->value==value) {
- *name = item->name;
+int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
+{
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ for(i=0; i<totitem; i++) {
+ if(item[i].value==value) {
+ *identifier = item[i].identifier;
return 1;
}
}
- return 0;
-}
-
-int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
-{
- const EnumPropertyItem *item= NULL;
- RNA_property_enum_items(ptr, prop, &item, NULL);
- return RNA_enum_identifier(item, value, identifier);
+ return 0;
}
const char *RNA_property_ui_name(PropertyRNA *prop)
@@ -1522,313 +1508,6 @@ int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, co
}
}
-int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
-{
- CollectionPropertyIterator iter;
- ArrayIterator *internal;
- char *arrayp;
-
- if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
- return 0;
-
- RNA_property_collection_begin(ptr, prop, &iter);
-
- if(iter.valid) {
- /* get data from array iterator and item property */
- internal= iter.internal;
- arrayp= (iter.valid)? iter.ptr.data: NULL;
-
- if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
- /* we might skip some items, so it's not a proper array */
- RNA_property_collection_end(&iter);
- return 0;
- }
-
- array->array= arrayp + itemprop->rawoffset;
- array->stride= internal->itemsize;
- array->len= ((char*)internal->endptr - arrayp)/internal->itemsize;
- array->type= itemprop->rawtype;
- }
- else
- memset(array, 0, sizeof(RawArray));
-
- RNA_property_collection_end(&iter);
-
- return 1;
-}
-
-#define RAW_GET(dtype, var, raw, a) \
-{ \
- switch(raw.type) { \
- case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \
- case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \
- case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \
- case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \
- case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \
- default: var = (dtype)0; \
- } \
-}
-
-#define RAW_SET(dtype, raw, a, var) \
-{ \
- switch(raw.type) { \
- case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \
- case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \
- case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \
- case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \
- case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \
- } \
-}
-
-static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
-{
- StructRNA *ptype;
- PointerRNA itemptr;
- PropertyRNA *itemprop, *iprop;
- PropertyType itemtype;
- RawArray in;
- int itemlen= 0;
-
- /* initialize in array, stride assumed 0 in following code */
- in.array= inarray;
- in.type= intype;
- in.len= inlen;
- in.stride= 0;
-
- ptype= RNA_property_pointer_type(ptr, prop);
-
- /* try to get item property pointer */
- RNA_pointer_create(NULL, ptype, NULL, &itemptr);
- itemprop= RNA_struct_find_property(&itemptr, propname);
-
- if(itemprop) {
- /* we have item property pointer */
- RawArray out;
-
- /* check type */
- itemtype= RNA_property_type(itemprop);
-
- if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
- BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
- return 0;
- }
-
- /* check item array */
- itemlen= RNA_property_array_length(itemprop);
-
- /* try to access as raw array */
- if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
- if(in.len != itemlen*out.len) {
- BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*itemlen, in.len);
- return 0;
- }
-
- /* matching raw types */
- if(out.type == in.type) {
- void *inp= in.array;
- void *outp= out.array;
- int a, size;
-
- itemlen= (itemlen == 0)? 1: itemlen;
-
- switch(out.type) {
- case PROP_RAW_CHAR: size= sizeof(char)*itemlen; break;
- case PROP_RAW_SHORT: size= sizeof(short)*itemlen; break;
- case PROP_RAW_INT: size= sizeof(int)*itemlen; break;
- case PROP_RAW_FLOAT: size= sizeof(float)*itemlen; break;
- case PROP_RAW_DOUBLE: size= sizeof(double)*itemlen; break;
- }
-
- for(a=0; a<out.len; a++) {
- if(set) memcpy(outp, inp, size);
- else memcpy(inp, outp, size);
-
- inp= (char*)inp + size;
- outp= (char*)outp + out.stride;
- }
-
- return 1;
- }
-
- /* could also be faster with non-matching types,
- * for now we just do slower loop .. */
- }
- }
-
- {
- void *tmparray= NULL;
- int tmplen= 0;
- int err= 0, j, a= 0;
-
- /* no item property pointer, can still be id property, or
- * property of a type derived from the collection pointer type */
- RNA_PROP_BEGIN(ptr, itemptr, prop) {
- if(itemptr.data) {
- if(itemprop) {
- /* we got the property already */
- iprop= itemprop;
- }
- else {
- /* not yet, look it up and verify if it is valid */
- iprop= RNA_struct_find_property(&itemptr, propname);
-
- if(iprop) {
- itemlen= RNA_property_array_length(iprop);
- itemtype= RNA_property_type(iprop);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Property named %s not found.", propname);
- err= 1;
- break;
- }
-
- if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
- BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
- err= 1;
- break;
- }
- }
-
- /* editable check */
- if(RNA_property_editable(&itemptr, iprop)) {
- if(a+itemlen > in.len) {
- BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more).", in.len);
- err= 1;
- break;
- }
-
- if(itemlen == 0) {
- /* handle conversions */
- if(set) {
- switch(itemtype) {
- case PROP_BOOLEAN: {
- int b;
- RAW_GET(int, b, in, a);
- RNA_property_boolean_set(&itemptr, iprop, b);
- break;
- }
- case PROP_INT: {
- int i;
- RAW_GET(int, i, in, a);
- RNA_property_int_set(&itemptr, iprop, i);
- break;
- }
- case PROP_FLOAT: {
- float f;
- RAW_GET(float, f, in, a);
- RNA_property_float_set(&itemptr, iprop, f);
- break;
- }
- default:
- break;
- }
- }
- else {
- switch(itemtype) {
- case PROP_BOOLEAN: {
- int b= RNA_property_boolean_get(&itemptr, iprop);
- RAW_SET(int, in, a, b);
- break;
- }
- case PROP_INT: {
- int i= RNA_property_int_get(&itemptr, iprop);
- RAW_SET(int, in, a, i);
- break;
- }
- case PROP_FLOAT: {
- float f= RNA_property_float_get(&itemptr, iprop);
- RAW_SET(float, in, a, f);
- break;
- }
- default:
- break;
- }
- }
- a++;
- }
- else {
- /* allocate temporary array if needed */
- if(tmparray && tmplen != itemlen) {
- MEM_freeN(tmparray);
- tmparray= NULL;
- }
- if(!tmparray) {
- tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
- tmplen= itemlen;
- }
-
- /* handle conversions */
- if(set) {
- switch(itemtype) {
- case PROP_BOOLEAN: {
- for(j=0; j<itemlen; j++, a++)
- RAW_GET(int, ((int*)tmparray)[j], in, a);
- RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
- break;
- }
- case PROP_INT: {
- for(j=0; j<itemlen; j++, a++)
- RAW_GET(int, ((int*)tmparray)[j], in, a);
- RNA_property_int_set_array(&itemptr, iprop, tmparray);
- break;
- }
- case PROP_FLOAT: {
- for(j=0; j<itemlen; j++, a++)
- RAW_GET(float, ((float*)tmparray)[j], in, a);
- RNA_property_float_set_array(&itemptr, iprop, tmparray);
- break;
- }
- default:
- break;
- }
- }
- else {
- switch(itemtype) {
- case PROP_BOOLEAN: {
- RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
- for(j=0; j<itemlen; j++, a++)
- RAW_SET(int, in, a, ((int*)tmparray)[j]);
- break;
- }
- case PROP_INT: {
- RNA_property_int_get_array(&itemptr, iprop, tmparray);
- for(j=0; j<itemlen; j++, a++)
- RAW_SET(int, in, a, ((int*)tmparray)[j]);
- break;
- }
- case PROP_FLOAT: {
- RNA_property_float_get_array(&itemptr, iprop, tmparray);
- for(j=0; j<itemlen; j++, a++)
- RAW_SET(float, in, a, ((float*)tmparray)[j]);
- break;
- }
- default:
- break;
- }
- }
- }
- }
- }
- }
- RNA_PROP_END;
-
- if(tmparray)
- MEM_freeN(tmparray);
-
- return !err;
- }
-}
-
-int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
-{
- return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
-}
-
-int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
-{
- return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
-}
-
/* Standard iterator functions */
void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
@@ -2373,13 +2052,14 @@ int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
{
PropertyRNA *prop= RNA_struct_find_property(ptr, name);
const EnumPropertyItem *item;
+ int a, totitem;
if(prop) {
- RNA_property_enum_items(ptr, prop, &item, NULL);
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
- for(; item->identifier; item++)
- if(strcmp(item->identifier, enumname) == 0)
- return (item->value == RNA_property_enum_get(ptr, prop));
+ for(a=0; a<totitem; a++)
+ if(strcmp(item[a].identifier, enumname) == 0)
+ return (item[a].value == RNA_property_enum_get(ptr, prop));
printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
return 0;
@@ -2552,12 +2232,17 @@ char *RNA_pointer_as_string(PointerRNA *ptr)
DynStr *dynstr= BLI_dynstr_new();
char *cstring;
+ PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
const char *propname;
int first_time = 1;
BLI_dynstr_append(dynstr, "{");
- RNA_STRUCT_BEGIN(ptr, prop) {
+ iterprop= RNA_struct_iterator_property(ptr->type);
+
+ for(RNA_property_collection_begin(ptr, iterprop, &iter); iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
propname = RNA_property_identifier(prop);
if(strcmp(propname, "rna_type")==0)
@@ -2571,8 +2256,8 @@ char *RNA_pointer_as_string(PointerRNA *ptr)
BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring);
MEM_freeN(cstring);
}
- RNA_STRUCT_END;
+ RNA_property_collection_end(&iter);
BLI_dynstr_append(dynstr, "}");
@@ -2764,17 +2449,6 @@ ParameterList *RNA_parameter_list_create(PointerRNA *ptr, FunctionRNA *func)
void RNA_parameter_list_free(ParameterList *parms)
{
- PropertyRNA *parm;
- int tot;
-
- parm= parms->func->cont.properties.first;
- for(tot= 0; parm; parm= parm->next) {
- if(parm->type == PROP_COLLECTION)
- BLI_freelistN((ListBase*)((char*)parms->data+tot));
-
- tot+= rna_parameter_size(parm);
- }
-
MEM_freeN(parms->data);
parms->data= NULL;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 3639d6d3fff..588c94380dc 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_action.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 3eb88e706e9..05d55d284a7 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_actuator.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 2ed47effec1..d119783766d 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_animation.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index caa970eff57..389257e9331 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_armature.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -443,30 +443,6 @@ void rna_EditBone_tail_selected_set(PointerRNA *ptr, int value)
else data->flag &= ~BONE_TIPSEL;
}
-static void rna_Armature_bones_next(CollectionPropertyIterator *iter)
-{
- ListBaseIterator *internal= iter->internal;
- Bone *bone= (Bone*)internal->link;
-
- if(bone->childbase.first)
- internal->link= (Link*)bone->childbase.first;
- else if(bone->next)
- internal->link= (Link*)bone->next;
- else {
- internal->link= NULL;
-
- do {
- bone= bone->parent;
- if(bone && bone->next) {
- internal->link= (Link*)bone->next;
- break;
- }
- } while(bone);
- }
-
- iter->valid= (internal->link != NULL);
-}
-
#else
static void rna_def_bone_common(StructRNA *srna, int editbone)
@@ -684,7 +660,6 @@ void rna_def_armature(BlenderRNA *brna)
/* Collections */
prop= RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL);
- RNA_def_property_collection_funcs(prop, 0, "rna_Armature_bones_next", 0, 0, 0, 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "Bone");
RNA_def_property_ui_text(prop, "Bones", "");
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 90617d01833..d3213c01846 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_brush.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 4814f9583a9..928086b951c 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_camera.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index cefd2316fbf..7f61125bc11 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_cloth.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -34,24 +34,9 @@
#include "BKE_modifier.h"
#include "DNA_cloth_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "WM_types.h"
#ifdef RNA_RUNTIME
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-
-static void rna_cloth_update(bContext *C, PointerRNA *ptr)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ptr->id.data;
-
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-}
-
static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings*)ptr->data;
@@ -180,50 +165,42 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "mingoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "maxgoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "defgoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalspring");
RNA_def_property_range(prop, 0.0f, 0.999f);
RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalfrict");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* mass */
prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "Mass", "Mass of cloth material.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "mass_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length", "rna_ClothSettings_mass_vgroup_set");
RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex group for fine control over mass distribution.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_float_funcs(prop, "rna_ClothSettings_gravity_get", "rna_ClothSettings_gravity_set", NULL);
RNA_def_property_ui_text(prop, "Gravity", "Gravity or external force vector.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* various */
@@ -231,73 +208,61 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "Cvi");
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "Air Damping", "Air has normally some thickness which slows falling things down.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "pin_cloth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
RNA_def_property_ui_text(prop, "Pin Cloth", "Define forces for vertices to stick to animated position.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalspring");
RNA_def_property_range(prop, 0.0f, 50.0);
RNA_def_property_ui_text(prop, "Pin Stiffness", "Pin (vertex target position) spring stiffness.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
RNA_def_property_range(prop, 4, 80);
RNA_def_property_ui_text(prop, "Quality", "Quality of the simulation in steps per frame (higher is better quality but slower).");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* springs */
prop= RNA_def_property(srna, "stiffness_scaling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
RNA_def_property_ui_text(prop, "Stiffness Scaling", "If enabled, stiffness can be scaled along a weight painted vertex group.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "Cdis");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "structural");
RNA_def_property_range(prop, 1.0f, 10000.0f);
RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_struct");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", "rna_ClothSettings_struct_vgroup_set");
RNA_def_property_ui_text(prop, "Structural Stiffness Vertex Group", "Vertex group for fine control over structural stiffness.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bending");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles).");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_bend");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_bend_set", NULL);
RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set");
RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* unused */
@@ -358,48 +323,40 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "enable_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "epsilon");
RNA_def_property_range(prop, 0.001f, 1.0f);
RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance between collision objects before collision response takes in, can be changed for each frame.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 80.0f);
RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "loop_count");
RNA_def_property_range(prop, 1, 20);
RNA_def_property_ui_text(prop, "Collision Quality", "How many collision iterations should be done. (higher is better quality but slower)");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* self collision */
prop= RNA_def_property(srna, "enable_self_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF);
RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_min_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
RNA_def_property_range(prop, 0.5f, 1.0f);
RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 80.0f);
RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower), can be changed for each frame.");
- RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
}
void RNA_def_cloth(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 179808ab66d..c1464ec87f2 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_color.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 8200a21f4ac..ec1676eea95 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_constraint.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -534,14 +534,6 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
srna= RNA_def_struct(brna, "CopyLocationConstraint", "Constraint");
RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copies the location of the target.");
-
- RNA_def_struct_sdna(srna, "bConstraint");
-
- prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE);
- RNA_def_property_float_sdna(prop, NULL, "headtail");
- RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1.");
- RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
-
RNA_def_struct_sdna_from(srna, "bLocateLikeConstraint", "data");
prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
@@ -590,6 +582,13 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_def_struct_sdna(srna, "bConstraint");
+
+ prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE);
+ RNA_def_property_float_sdna(prop, NULL, "headtail");
+ RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_minmax(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 07a50235733..7624d4a1144 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_context.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index 4d5ef7aa123..47399090b4e 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_controller.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 41a47e279e9..c592625c7dc 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_curve.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 715f03bb3f1..98a2ae8b32d 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_define.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -112,7 +112,7 @@ StructDefRNA *rna_find_struct_def(StructRNA *srna)
return NULL;
}
-PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop)
+PropertyDefRNA *rna_find_struct_property_def(PropertyRNA *prop)
{
StructDefRNA *dsrna;
PropertyDefRNA *dprop;
@@ -123,7 +123,7 @@ PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop)
return NULL;
}
- dsrna= rna_find_struct_def(srna);
+ dsrna= rna_find_struct_def(DefRNA.laststruct);
dprop= dsrna->cont.properties.last;
for (; dprop; dprop= dprop->prev)
if (dprop->prop==prop)
@@ -150,7 +150,7 @@ PropertyDefRNA *rna_find_property_def(PropertyRNA *prop)
return NULL;
}
- dprop= rna_find_struct_property_def(DefRNA.laststruct, prop);
+ dprop= rna_find_struct_property_def(prop);
if (dprop)
return dprop;
@@ -1311,7 +1311,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, const char *stru
StructDefRNA *ds;
PropertyDefRNA *dp;
- dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
+ dp= rna_find_struct_property_def(prop);
if (dp==NULL) return NULL;
ds= rna_find_struct_def((StructRNA*)dp->cont);
@@ -1371,7 +1371,7 @@ void RNA_def_property_boolean_negative_sdna(PropertyRNA *prop, const char *struc
RNA_def_property_boolean_sdna(prop, structname, propname, booleanbit);
- dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
+ dp= rna_find_struct_property_def(prop);
if(dp)
dp->booleannegative= 1;
@@ -1468,7 +1468,7 @@ void RNA_def_property_enum_bitflag_sdna(PropertyRNA *prop, const char *structnam
RNA_def_property_enum_sdna(prop, structname, propname);
- dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
+ dp= rna_find_struct_property_def(prop);
if(dp)
dp->enumbitflags= 1;
@@ -1946,7 +1946,7 @@ PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont_, const char *ide
return prop;
}
-PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value,
+PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, EnumPropertyItem *items, int default_value,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont= cont_;
@@ -2249,6 +2249,7 @@ int rna_parameter_size(PropertyRNA *parm)
#endif
}
case PROP_COLLECTION:
+ /* XXX does not work yet */
return sizeof(ListBase);
}
}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 806219ec6bf..70e511de323 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_fcurve.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 4e047ff7772..ac51aa6d0d7 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_fluidsim.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index 1406ad1ae60..82bdd66802a 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_group.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 4a6fdf5a734..7c8b0c3bf8e 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_image.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -35,8 +35,6 @@
#include "BKE_context.h"
#include "BKE_image.h"
-#include "WM_types.h"
-
#ifdef RNA_RUNTIME
static void rna_Image_animated_update(bContext *C, PointerRNA *ptr)
@@ -135,19 +133,16 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
RNA_def_property_ui_text(prop, "Filename", "Image/Movie file name.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_source_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
RNA_def_property_ui_text(prop, "Source", "Where the image comes from.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
RNA_def_property_ui_text(prop, "Type", "How to generate the image.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
@@ -157,105 +152,90 @@ static void rna_def_image(BlenderRNA *brna)
prop= RNA_def_property(srna, "fields", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS);
RNA_def_property_ui_text(prop, "Fields", "Use fields of the image.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "odd_fields", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_STD_FIELD);
RNA_def_property_ui_text(prop, "Odd Fields", "Standard field toggle.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "antialias", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANTIALI);
RNA_def_property_ui_text(prop, "Anti-alias", "Toggles image anti-aliasing, only works with solid colors");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "premultiply", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL);
RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
/* generated image (image_generated_change_cb) */
prop= RNA_def_property(srna, "generated_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "gen_type");
RNA_def_property_enum_items(prop, prop_generated_type_items);
RNA_def_property_ui_text(prop, "Generated Type", "Generated image type.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gen_x");
RNA_def_property_range(prop, 1, 16384);
RNA_def_property_ui_text(prop, "Generated Width", "Generated image width.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gen_y");
RNA_def_property_range(prop, 1, 16384);
RNA_def_property_ui_text(prop, "Generated Height", "Generated image height.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
/* realtime properties */
prop= RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_mapping_items);
RNA_def_property_ui_text(prop, "Mapping", "Mapping type to use for this image in the game engine.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "display_aspect", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_sdna(prop, NULL, "aspx");
RNA_def_property_array(prop, 2);
RNA_def_property_range(prop, 0.1f, 5000.0f);
RNA_def_property_ui_text(prop, "Display Aspect", "Display Aspect for this image, does not affect rendering.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "animated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TWINANIM);
RNA_def_property_ui_text(prop, "Animated", "Use as animated texture in the game engine.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
+ RNA_def_property_update(prop, 0, "rna_Image_animated_update");
prop= RNA_def_property(srna, "animation_start", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "twsta");
RNA_def_property_range(prop, 0, 128);
RNA_def_property_ui_text(prop, "Animation Start", "Start frame of an animated texture.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
+ RNA_def_property_update(prop, 0, "rna_Image_animated_update");
prop= RNA_def_property(srna, "animation_end", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "twend");
RNA_def_property_range(prop, 0, 128);
RNA_def_property_ui_text(prop, "Animation End", "End frame of an animated texture.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
+ RNA_def_property_update(prop, 0, "rna_Image_animated_update");
prop= RNA_def_property(srna, "animation_speed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "animspeed");
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Animation Speed", "Speed of the animation in frames per second.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "tiles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TILES);
RNA_def_property_ui_text(prop, "Tiles", "Use of tilemode for faces (default shift-LMB to pick the tile for selected faces).");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "tiles_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "xrep");
RNA_def_property_range(prop, 1, 16);
RNA_def_property_ui_text(prop, "Tiles X", "Degree of repetition in the X direction.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "tiles_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "yrep");
RNA_def_property_range(prop, 1, 16);
RNA_def_property_ui_text(prop, "Tiles Y", "Degree of repetition in the Y direction.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "clamp_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_U);
RNA_def_property_ui_text(prop, "Clamp X", "Disable texture repeating horizontally.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
prop= RNA_def_property(srna, "clamp_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_V);
RNA_def_property_ui_text(prop, "Clamp Y", "Disable texture repeating vertically.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
}
void RNA_def_image(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 3d66682771d..a41f522bb0f 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_internal.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -145,6 +145,7 @@ void RNA_def_object_force(struct BlenderRNA *brna);
void RNA_def_packedfile(struct BlenderRNA *brna);
void RNA_def_particle(struct BlenderRNA *brna);
void RNA_def_pose(struct BlenderRNA *brna);
+void RNA_def_radio(struct BlenderRNA *brna);
void RNA_def_rna(struct BlenderRNA *brna);
void RNA_def_scene(struct BlenderRNA *brna);
void RNA_def_screen(struct BlenderRNA *brna);
@@ -255,7 +256,6 @@ void rna_freelistN(struct ListBase *listbase);
StructDefRNA *rna_find_struct_def(StructRNA *srna);
FunctionDefRNA *rna_find_function_def(FunctionRNA *func);
PropertyDefRNA *rna_find_parameter_def(PropertyRNA *parm);
-PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop);
/* Pointer Handling */
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 401b430ebc9..3cf250151c7 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_internal_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -146,10 +146,6 @@ struct PropertyRNA {
/* callback for testing if editable/evaluated */
EditableFunc editable;
-
- /* raw access */
- int rawoffset;
- RawPropertyType rawtype;
};
/* Property Types */
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 71e424bbd69..b97dd95c4d4 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_key.c 19382 2009-03-23 13:24:48Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index a49b4377d9d..c6cf2b0a410 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_lamp.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -253,11 +253,11 @@ static void rna_def_lamp(BlenderRNA *brna)
PropertyRNA *prop;
static EnumPropertyItem prop_type_items[] = {
- {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source."},
- {LA_SUN, "SUN", ICON_LAMP_SUN, "Sun", "Constant direction parallel ray light source."},
- {LA_SPOT, "SPOT", ICON_LAMP_SPOT, "Spot", "Directional cone light source."},
- {LA_HEMI, "HEMI", ICON_LAMP_HEMI, "Hemi", "180 degree constant light source."},
- {LA_AREA, "AREA", ICON_LAMP_AREA, "Area", "Directional area light source."},
+ {LA_LOCAL, "POINT", 0, "Point", "Omnidirectional point light source."},
+ {LA_SUN, "SUN", 0, "Sun", "Constant direction parallel ray light source."},
+ {LA_SPOT, "SPOT", 0, "Spot", "Directional cone light source."},
+ {LA_HEMI, "HEMI", 0, "Hemi", "180 degree constant light source."},
+ {LA_AREA, "AREA", 0, "Area", "Directional area light source."},
{0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "Lamp", "ID");
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index f67267ce0d0..3af448b0233 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_lattice.c 19382 2009-03-23 13:24:48Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 26fc3c2941e..6b1ce8c02ae 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_main.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -264,7 +264,7 @@ void RNA_def_main(BlenderRNA *brna)
{
prop= RNA_def_property(srna, lists[i][0], PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, lists[i][1]);
- RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0, 0);
+ RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, "add_mesh", "remove_mesh");
RNA_def_property_ui_text(prop, lists[i][3], lists[i][4]);
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 6d56b2b00f9..2d699b6b229 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_main_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 41f31594f6e..66e30f7ee50 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_material.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index e56760f5ca3..25b8739e074 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_mesh.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -234,29 +234,6 @@ static int rna_Mesh_uv_layers_length(PointerRNA *ptr)
return rna_CustomDataLayer_length(ptr, CD_MTFACE);
}
-static PointerRNA rna_Mesh_active_uv_layer_get(PointerRNA *ptr)
-{
- Mesh *me= (Mesh*)ptr->data;
- int index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- CustomDataLayer *cdl= (index == -1)? NULL: &me->fdata.layers[index];
-
- return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
-}
-
-static void rna_Mesh_active_uv_layer_set(PointerRNA *ptr, PointerRNA value)
-{
- Mesh *me= (Mesh*)ptr->data;
- CustomDataLayer *cdl;
- int a;
-
- for(cdl=me->fdata.layers, a=0; a<me->fdata.totlayer; cdl++, a++) {
- if(value.data == cdl) {
- CustomData_set_layer_active_index(&me->fdata, CD_MTFACE, a);
- return;
- }
- }
-}
-
static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values)
{
MTFace *mtface= (MTFace*)ptr->data;
@@ -371,29 +348,6 @@ static int rna_Mesh_vcol_layers_length(PointerRNA *ptr)
return rna_CustomDataLayer_length(ptr, CD_MCOL);
}
-static PointerRNA rna_Mesh_active_vcol_layer_get(PointerRNA *ptr)
-{
- Mesh *me= (Mesh*)ptr->data;
- int index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
- CustomDataLayer *cdl= (index == -1)? NULL: &me->fdata.layers[index];
-
- return rna_pointer_inherit_refine(ptr, &RNA_MeshColorLayer, cdl);
-}
-
-static void rna_Mesh_active_vcol_layer_set(PointerRNA *ptr, PointerRNA value)
-{
- Mesh *me= (Mesh*)ptr->data;
- CustomDataLayer *cdl;
- int a;
-
- for(cdl=me->fdata.layers, a=0; a<me->fdata.totlayer; cdl++, a++) {
- if(value.data == cdl) {
- CustomData_set_layer_active_index(&me->fdata, CD_MCOL, a);
- return;
- }
- }
-}
-
static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
@@ -1121,34 +1075,18 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "MeshSticky");
RNA_def_property_ui_text(prop, "Sticky", "Sticky texture coordinates.");
- /* UV layers */
-
prop= RNA_def_property(srna, "uv_layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_layers_begin", 0, 0, 0, "rna_Mesh_uv_layers_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
RNA_def_property_ui_text(prop, "UV Layers", "");
- prop= RNA_def_property(srna, "active_uv_layer", PROP_POINTER, PROP_UNSIGNED);
- RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_uv_layer_get", "rna_Mesh_active_uv_layer_set", NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Active UV Layer", "Active UV layer.");
-
- /* VCol layers */
-
prop= RNA_def_property(srna, "vcol_layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_vcol_layers_begin", 0, 0, 0, "rna_Mesh_vcol_layers_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshColorLayer");
RNA_def_property_ui_text(prop, "Vertex Color Layers", "");
- prop= RNA_def_property(srna, "active_vcol_layer", PROP_POINTER, PROP_UNSIGNED);
- RNA_def_property_struct_type(prop, "MeshColorLayer");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_vcol_layer_get", "rna_Mesh_active_vcol_layer_set", NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer.");
-
prop= RNA_def_property(srna, "float_layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_float_layers_begin", 0, 0, 0, "rna_Mesh_float_layers_length", 0, 0, 0, 0);
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 26fb77777d7..02c079920ea 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_mesh_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index 5f95336af2d..ce5b883f0a9 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_meta.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 9b3ff6e74a0..4c7bb3f52da 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_modifier.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -41,35 +41,35 @@
#include "WM_types.h"
EnumPropertyItem modifier_type_items[] ={
- {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
- {eModifierType_Array, "ARRAY", ICON_MOD_ARRAY, "Array", ""},
- {eModifierType_Bevel, "BEVEL", ICON_MOD_BEVEL, "Bevel", ""},
- {eModifierType_Boolean, "BOOLEAN", ICON_MOD_BOOLEAN, "Boolean", ""},
- {eModifierType_Build, "BUILD", ICON_MOD_BUILD, "Build", ""},
- {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
- {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""},
- {eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""},
- {eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""},
- {eModifierType_Decimate, "DECIMATE", ICON_MOD_DECIM, "Decimate", ""},
- {eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""},
- {eModifierType_EdgeSplit, "EDGE_SPLIT", ICON_MOD_EDGESPLIT, "Edge Split", ""},
- {eModifierType_Explode, "EXPLODE", ICON_MOD_EXPLODE, "Explode", ""},
- {eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
- {eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""},
- {eModifierType_Lattice, "LATTICE", ICON_MOD_LATTICE, "Lattice", ""},
- {eModifierType_Mask, "MASK", ICON_MOD_MASK, "Mask", ""},
- {eModifierType_MeshDeform, "MESH_DEFORM", ICON_MOD_MESHDEFORM, "Mesh Deform", ""},
- {eModifierType_Mirror, "MIRROR", ICON_MOD_MIRROR, "Mirror", ""},
- {eModifierType_Multires, "MULTIRES", ICON_MOD_MULTIRES, "Multires", ""},
- {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", ICON_MOD_PARTICLES, "Particle Instance", ""},
- {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particle System", ""},
- {eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""},
- {eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""},
- {eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
- {eModifierType_Softbody, "SOFTBODY", ICON_MOD_SOFT, "Softbody", ""},
- {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subsurf", ""},
- {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
- {eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
+ {eModifierType_Armature, "ARMATURE", 0, "Armature", ""},
+ {eModifierType_Array, "ARRAY", 0, "Array", ""},
+ {eModifierType_Bevel, "BEVEL", 0, "Bevel", ""},
+ {eModifierType_Boolean, "BOOLEAN", 0, "Boolean", ""},
+ {eModifierType_Build, "BUILD", 0, "Build", ""},
+ {eModifierType_Cast, "CAST", 0, "Cast", ""},
+ {eModifierType_Cloth, "CLOTH", 0, "Cloth", ""},
+ {eModifierType_Collision, "COLLISION", 0, "Collision", ""},
+ {eModifierType_Curve, "CURVE", 0, "Curve", ""},
+ {eModifierType_Decimate, "DECIMATE", 0, "Decimate", ""},
+ {eModifierType_Displace, "DISPLACE", 0, "Displace", ""},
+ {eModifierType_EdgeSplit, "EDGE_SPLIT", 0, "Edge Split", ""},
+ {eModifierType_Explode, "EXPLODE", 0, "Explode", ""},
+ {eModifierType_Fluidsim, "FLUID_SIMULATION", 0, "Fluid Simulation", ""},
+ {eModifierType_Hook, "HOOK", 0, "Hook", ""},
+ {eModifierType_Lattice, "LATTICE", 0, "Lattice", ""},
+ {eModifierType_Mask, "MASK", 0, "Mask", ""},
+ {eModifierType_MeshDeform, "MESH_DEFORM", 0, "Mesh Deform", ""},
+ {eModifierType_Mirror, "MIRROR", 0, "Mirror", ""},
+ {eModifierType_Multires, "MULTIRES", 0, "Multires", ""},
+ {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", 0, "Particle Instance", ""},
+ {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", 0, "Particle System", ""},
+ {eModifierType_Shrinkwrap, "SHRINKWRAP", 0, "Shrinkwrap", ""},
+ {eModifierType_SimpleDeform, "SIMPLE_DEFORM", 0, "Simple Deform", ""},
+ {eModifierType_Smooth, "SMOOTH", 0, "Smooth", ""},
+ {eModifierType_Softbody, "SOFTBODY", 0, "Softbody", ""},
+ {eModifierType_Subsurf, "SUBSURF", 0, "Subsurf", ""},
+ {eModifierType_UVProject, "UV_PROJECT", 0, "UV Project", ""},
+ {eModifierType_Wave, "WAVE", 0, "Wave", ""},
{0, NULL, 0, NULL, NULL}};
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index b35b02b2063..bad3d36bfc2 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_nodetree.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h
index 47a7be163b1..cff3984a56a 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_nodetree_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 9b3100c733b..8fa07ecf813 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_object.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -33,7 +33,6 @@
#include "DNA_customdata_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
@@ -241,25 +240,6 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MaterialSlot, ob->mat+ob->actcol);
}
-static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max)
-{
- Object *ob= (Object*)ptr->id.data;
- *min= 1;
- *max= BLI_countlist(&ob->particlesystem);
-}
-
-static int rna_Object_active_particle_system_index_get(PointerRNA *ptr)
-{
- Object *ob= (Object*)ptr->id.data;
- return psys_get_current_num(ob) + 1;
-}
-
-static void rna_Object_active_particle_system_index_set(struct PointerRNA *ptr, int value)
-{
- Object *ob= (Object*)ptr->id.data;
- psys_set_current_num(ob, value);
-}
-
#if 0
static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value)
{
@@ -429,13 +409,11 @@ static void rna_def_material_slot(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, "rna_MaterialSlot_material_get", "rna_MaterialSlot_material_set", NULL);
RNA_def_property_ui_text(prop, "Material", "Material datablock used by this material slot.");
- RNA_def_property_update(prop, NC_OBJECT|ND_SHADING, "rna_Object_update");
prop= RNA_def_property(srna, "link", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, link_items);
RNA_def_property_enum_funcs(prop, "rna_MaterialSlot_link_get", "rna_MaterialSlot_link_set", NULL);
RNA_def_property_ui_text(prop, "Link", "Link material to object or the object's data.");
- RNA_def_property_update(prop, NC_OBJECT|ND_SHADING, "rna_Object_update");
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_MaterialSlot_name_get", "rna_MaterialSlot_name_length", NULL);
@@ -948,10 +926,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_Object_active_particle_system_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed");
- prop= RNA_def_property(srna, "active_particle_system_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Object_active_particle_system_index_get", "rna_Object_active_particle_system_index_set", "rna_Object_active_particle_system_index_range");
- RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot.");
-
/* restrict */
prop= RNA_def_property(srna, "restrict_view", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 053ab115b3b..4ed97164988 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_object_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 4d8c728db12..41ff8c98f73 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_object_force.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -31,225 +31,9 @@
#include "DNA_object_types.h"
#include "DNA_object_force.h"
-#include "DNA_scene_types.h"
-
-#include "WM_types.h"
#ifdef RNA_RUNTIME
-#include "MEM_guardedalloc.h"
-
-#include "BKE_context.h"
-#include "BKE_pointcache.h"
-#include "BKE_depsgraph.h"
-
-#include "BLI_blenlib.h"
-
-static void rna_Cache_change(bContext *C, PointerRNA *ptr)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PointCache *cache = (PointCache*)ptr->data;
- PTCacheID *pid = NULL;
- ListBase pidlist;
-
- if(!ob)
- return;
-
- cache->flag |= PTCACHE_OUTDATED;
-
- BKE_ptcache_ids_from_object(&pidlist, ob);
-
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- if(pid->cache==cache)
- break;
- }
-
- if(pid)
- BKE_ptcache_update_info(pid);
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
-{
- Object *ob = CTX_data_active_object(C);
- PointCache *cache = (PointCache*)ptr->data;
- PTCacheID *pid = NULL;
- ListBase pidlist;
-
- if(!ob)
- return;
-
- BKE_ptcache_ids_from_object(&pidlist, ob);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- if(pid->cache==cache)
- break;
- }
-
- if(pid)
- BKE_ptcache_toggle_disk_cache(pid);
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
-{
- Object *ob = CTX_data_active_object(C);
- PointCache *cache = (PointCache*)ptr->data;
- PTCacheID *pid = NULL, *pid2;
- ListBase pidlist;
- int new_name = 1;
- char name[80];
-
- if(!ob)
- return;
-
- /* TODO: check for proper characters */
-
- BKE_ptcache_ids_from_object(&pidlist, ob);
-
- for(pid=pidlist.first; pid; pid=pid->next) {
- if(pid->cache==cache)
- pid2 = pid;
- else if(strcmp(cache->name, "") && strcmp(cache->name,pid->cache->name)==0) {
- /*TODO: report "name exists" to user */
- strcpy(cache->name, cache->prev_name);
- new_name = 0;
- }
- }
-
- if(new_name) {
- if(pid2 && cache->flag & PTCACHE_DISK_CACHE) {
- strcpy(name, cache->name);
- strcpy(cache->name, cache->prev_name);
-
- cache->flag &= ~PTCACHE_DISK_CACHE;
-
- BKE_ptcache_toggle_disk_cache(pid2);
-
- strcpy(cache->name, name);
-
- cache->flag |= PTCACHE_DISK_CACHE;
-
- BKE_ptcache_toggle_disk_cache(pid2);
- }
-
- strcpy(cache->prev_name, cache->name);
- }
-
- BLI_freelistN(&pidlist);
-}
-
-static int rna_SoftBodySettings_use_edges_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_EDGES) != 0);
-}
-
-static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_EDGES;
- else data->softflag &= ~OB_SB_EDGES;
-}
-
-static int rna_SoftBodySettings_use_goal_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_GOAL) != 0);
-}
-
-static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_GOAL;
- else data->softflag &= ~OB_SB_GOAL;
-}
-
-static int rna_SoftBodySettings_stiff_quads_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_QUADS) != 0);
-}
-
-static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_QUADS;
- else data->softflag &= ~OB_SB_QUADS;
-}
-
-static int rna_SoftBodySettings_self_collision_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_SELF) != 0);
-}
-
-static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_SELF;
- else data->softflag &= ~OB_SB_SELF;
-}
-
-static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_AERO_ANGLE) != 0);
-}
-
-static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_AERO_ANGLE;
- else data->softflag &= ~OB_SB_AERO_ANGLE;
-}
-
-static int rna_SoftBodySettings_enabled_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_ENABLE) != 0);
-}
-
-#if 0
-static void rna_SoftBodySettings_enabled_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_ENABLE;
- else data->softflag &= ~OB_SB_ENABLE;
-}
-#endif
-
-static int rna_SoftBodySettings_face_collision_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_FACECOLL) != 0);
-}
-
-static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_FACECOLL;
- else data->softflag &= ~OB_SB_FACECOLL;
-}
-
-static int rna_SoftBodySettings_edge_collision_get(PointerRNA *ptr)
-{
- Object *data= (Object*)(ptr->data);
- return (((data->softflag) & OB_SB_EDGECOLL) != 0);
-}
-
-static void rna_SoftBodySettings_edge_collision_set(PointerRNA *ptr, int value)
-{
- Object *data= (Object*)(ptr->data);
- if(value) data->softflag |= OB_SB_EDGECOLL;
- else data->softflag &= ~OB_SB_EDGECOLL;
-}
-
#else
static void rna_def_pointcache(BlenderRNA *brna)
@@ -270,47 +54,12 @@ static void rna_def_pointcache(BlenderRNA *brna)
RNA_def_property_range(prop, 1, 300000);
RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
- prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "step");
- RNA_def_property_range(prop, 1, 20);
- RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-
/* flags */
prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
prop= RNA_def_property(srna, "baking", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKING);
-
- prop= RNA_def_property(srna, "disk_cache", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_DISK_CACHE);
- RNA_def_property_ui_text(prop, "Disk Cache", "Save cache files to disk");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache");
-
- prop= RNA_def_property(srna, "outdated", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Cache is outdated", "");
-
- prop= RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "name");
- RNA_def_property_ui_text(prop, "Name", "Cache name");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
-
- prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
- RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-
- prop= RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "info");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
}
static void rna_def_collision(BlenderRNA *brna)
@@ -414,7 +163,6 @@ static void rna_def_field(BlenderRNA *brna)
srna= RNA_def_struct(brna, "FieldSettings", NULL);
RNA_def_struct_sdna(srna, "PartDeflect");
RNA_def_struct_ui_text(srna, "Field Settings", "Field settings for an object in physics simulation.");
- RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
/* Enums */
@@ -557,206 +305,10 @@ static void rna_def_game_softbody(BlenderRNA *brna)
static void rna_def_softbody(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem collision_type_items[] = {
- {SBC_MODE_MANUAL, "MANUAL", 0, "Manual", "Manual adjust"},
- {SBC_MODE_AVG, "AVERAGE", 0, "Average", "Average Spring lenght * Ball Size"},
- {SBC_MODE_MIN, "MINIMAL", 0, "Minimal", "Minimal Spring lenght * Ball Size"},
- {SBC_MODE_MAX, "MAXIMAL", 0, "Maximal", "Maximal Spring lenght * Ball Size"},
- {SBC_MODE_AVGMINMAX, "MINMAX", 0, "AvMinMax", "(Min+Max)/2 * Ball Size"},
- {0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "SoftBodySettings", NULL);
RNA_def_struct_sdna(srna, "SoftBody");
RNA_def_struct_ui_text(srna, "Soft Body Settings", "Soft body simulation settings for an object.");
-
- /* General Settings */
-
- prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "mediafrict");
- RNA_def_property_range(prop, 0.0f, 50.0f);
- RNA_def_property_ui_text(prop, "Friction", "General media friction for point movements");
-
- prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "nodemass");
- RNA_def_property_range(prop, 0.0f, 50000.0f);
- RNA_def_property_ui_text(prop, "Mass", "");
-
- prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "grav");
- RNA_def_property_range(prop, -10.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Gravitation", "Apply gravitation to point movement");
-
- prop= RNA_def_property(srna, "speed", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "physics_speed");
- RNA_def_property_range(prop, 0.01f, 100.0f);
- RNA_def_property_ui_text(prop, "Speed", "Tweak timing for physics to control frequency and speed");
-
- /* Goal */
-
- /*prop= RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "vertgroup");
- RNA_def_property_ui_text(prop, "Vertex Group", "Use control point weight values");*/
-
- prop= RNA_def_property(srna, "goal_min", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "mingoal");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
-
- prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "maxgoal");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
-
- prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "defgoal");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
-
- prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "goalspring");
- RNA_def_property_range(prop, 0.0f, 0.999f);
- RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
-
- prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "goalfrict");
- RNA_def_property_range(prop, 0.0f, 50.0f);
- RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
-
- /* Edge Spring Settings */
-
- prop= RNA_def_property(srna, "pull", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "inspring");
- RNA_def_property_range(prop, 0.0f, 0.999f);
- RNA_def_property_ui_text(prop, "Pull", "Edge spring stiffness when longer than rest length");
-
- prop= RNA_def_property(srna, "push", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "inpush");
- RNA_def_property_range(prop, 0.0f, 0.999f);
- RNA_def_property_ui_text(prop, "Push", "Edge spring stiffness when shorter than rest length");
-
- prop= RNA_def_property(srna, "damp", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "infrict");
- RNA_def_property_range(prop, 0.0f, 50.0f);
- RNA_def_property_ui_text(prop, "Damp", "Edge spring friction");
-
- prop= RNA_def_property(srna, "spring_lenght", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "springpreload");
- RNA_def_property_range(prop, 0.0f, 200.0f);
- RNA_def_property_ui_text(prop, "SL", "Alter spring lenght to shrink/blow up (unit %) 0 to disable");
-
- prop= RNA_def_property(srna, "aero", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "aeroedge");
- RNA_def_property_range(prop, 0.0f, 30000.0f);
- RNA_def_property_ui_text(prop, "Aero", "Make edges 'sail'");
-
- prop= RNA_def_property(srna, "plastic", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "plastic");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Plastic", "Permanent deform");
-
- prop= RNA_def_property(srna, "bending", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "secondspring");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Bending", "Bending Stiffness");
-
- prop= RNA_def_property(srna, "shear", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "shearstiff");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Shear", "Shear Stiffness");
-
- /* Collision */
-
- prop= RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "sbc_mode");
- RNA_def_property_enum_items(prop, collision_type_items);
- RNA_def_property_ui_text(prop, "Collision Type", "Choose Collision Type");
-
- prop= RNA_def_property(srna, "ball_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "colball");
- RNA_def_property_range(prop, -10.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Ball Size", "Absolute ball size or factor if not manual adjusted");
-
- prop= RNA_def_property(srna, "ball_stiff", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "ballstiff");
- RNA_def_property_range(prop, 0.001f, 100.0f);
- RNA_def_property_ui_text(prop, "Ball Size", "Ball inflating presure");
-
- prop= RNA_def_property(srna, "ball_damp", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "balldamp");
- RNA_def_property_range(prop, 0.001f, 1.0f);
- RNA_def_property_ui_text(prop, "Ball Size", "Blending to inelastic collision");
-
- /* Solver */
-
- prop= RNA_def_property(srna, "error_limit", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rklimit");
- RNA_def_property_range(prop, 0.001f, 10.0f);
- RNA_def_property_ui_text(prop, "Error Limit", "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed");
-
- prop= RNA_def_property(srna, "minstep", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "minloops");
- RNA_def_property_range(prop, 0, 30000);
- RNA_def_property_ui_text(prop, "Min Step", "Minimal # solver steps/frame");
-
- prop= RNA_def_property(srna, "maxstep", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "maxloops");
- RNA_def_property_range(prop, 0, 30000);
- RNA_def_property_ui_text(prop, "Max Step", "Maximal # solver steps/frame");
-
- prop= RNA_def_property(srna, "choke", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "choke");
- RNA_def_property_range(prop, 0, 100);
- RNA_def_property_ui_text(prop, "Choke", "'Viscosity' inside collision target");
-
- prop= RNA_def_property(srna, "fuzzy", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "fuzzyness");
- RNA_def_property_range(prop, 1, 100);
- RNA_def_property_ui_text(prop, "Fuzzy", "Fuzzyness while on collision, high values make collsion handling faster but less stable");
-
- prop= RNA_def_property(srna, "auto_step", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_OLDERR);
- RNA_def_property_ui_text(prop, "V", "Use velocities for automagic step sizes");
-
- prop= RNA_def_property(srna, "diagnose", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_MONITOR);
- RNA_def_property_ui_text(prop, "Print Performance to Console", "Turn on SB diagnose console prints");
-
- /* Flags */
-
- prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_enabled_get", "rna_SoftBodySettings_enabled_set");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Enable", "Sets object to become soft body.");
-
- prop= RNA_def_property(srna, "use_goal", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_goal_get", "rna_SoftBodySettings_use_goal_set");
- RNA_def_property_ui_text(prop, "Use Goal", "Define forces for vertices to stick to animated position.");
-
- prop= RNA_def_property(srna, "use_edges", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_edges_get", "rna_SoftBodySettings_use_edges_set");
- RNA_def_property_ui_text(prop, "Use Edges", "Use Edges as springs");
-
- prop= RNA_def_property(srna, "stiff_quads", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_stiff_quads_get", "rna_SoftBodySettings_stiff_quads_set");
- RNA_def_property_ui_text(prop, "Stiff Quads", "Adds diagonal springs on 4-gons.");
-
- prop= RNA_def_property(srna, "edge_collision", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_edge_collision_get", "rna_SoftBodySettings_edge_collision_set");
- RNA_def_property_ui_text(prop, "Edge Collision", "Edges collide too.");
-
- prop= RNA_def_property(srna, "face_collision", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_face_collision_get", "rna_SoftBodySettings_face_collision_set");
- RNA_def_property_ui_text(prop, "Face Collision", "Faces collide too, SLOOOOOW warning.");
-
- prop= RNA_def_property(srna, "new_aero", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_new_aero_get", "rna_SoftBodySettings_new_aero_set");
- RNA_def_property_ui_text(prop, "N", "New aero(uses angle and length).");
-
- prop= RNA_def_property(srna, "self_collision", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_self_collision_get", "rna_SoftBodySettings_self_collision_set");
- RNA_def_property_ui_text(prop, "Self Collision", "Enable naive vertex ball self collision.");
}
void RNA_def_object_force(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index 6b9a708f555..6b6db71ef87 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_packedfile.c 19382 2009-03-23 13:24:48Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index d60a215b498..efcd9dbd434 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_particle.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -38,7 +38,6 @@
#include "DNA_scene_types.h"
#include "WM_types.h"
-#include "WM_api.h"
#ifdef RNA_RUNTIME
@@ -46,110 +45,48 @@
#include "BKE_depsgraph.h"
#include "BKE_particle.h"
-#include "BLI_arithb.h"
-
-/* property update functions */
static void rna_Particle_redo(bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
- if(ptr->type==&RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem*)ptr->data;
- Object *ob = psys_find_object(scene, psys);
-
- psys->recalc = PSYS_RECALC_REDO;
-
- if(ob)
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- }
- else {
+ if(ptr->type==&RNA_ParticleSystem)
+ part = ((ParticleSystem*)ptr->data)->part;
+ else
part = ptr->id.data;
- psys_flush_particle_settings(scene, part, PSYS_RECALC_REDO);
- }
+
+ psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_REDO);
}
static void rna_Particle_reset(bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
-
- if(ptr->type==&RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem*)ptr->data;
- Object *ob = psys_find_object(scene, psys);
-
- psys->recalc = PSYS_RECALC_RESET;
-
- if(ob) {
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- }
- }
- else {
+ if(ptr->type==&RNA_ParticleSystem)
+ part = ((ParticleSystem*)ptr->data)->part;
+ else
part = ptr->id.data;
- psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
- }
+
+ psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_RESET|PSYS_RECALC_REDO);
}
static void rna_Particle_change_type(bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
-
- if(ptr->type==&RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem*)ptr->data;
- Object *ob = psys_find_object(scene, psys);
-
- psys->recalc = PSYS_RECALC_RESET|PSYS_RECALC_TYPE;
-
- if(ob) {
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- }
- }
- else {
+ if(ptr->type==&RNA_ParticleSystem)
+ part = ((ParticleSystem*)ptr->data)->part;
+ else
part = ptr->id.data;
- psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE);
- }
+
+ psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE|PSYS_RECALC_REDO);
}
static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
-
- if(ptr->type==&RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem*)ptr->data;
- Object *ob = psys_find_object(scene, psys);
-
- psys->recalc = PSYS_RECALC_CHILD;
-
- if(ob)
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- }
- else {
+ if(ptr->type==&RNA_ParticleSystem)
+ part = ((ParticleSystem*)ptr->data)->part;
+ else
part = ptr->id.data;
- psys_flush_particle_settings(scene, part, PSYS_RECALC_CHILD);
- }
-}
-static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
-{
- Object *ob= (Object*)ptr->id.data;
- ParticleSettings *part = psys_get_current(ob)->part;
-
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part);
-}
-
-static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value)
-{
- Object *ob= (Object*)ptr->id.data;
- ParticleSystem *psys = psys_get_current(ob);
-
- if(psys->part)
- psys->part->id.us--;
-
- psys->part = (ParticleSettings *)value.data;
-
- if(psys->part)
- psys->part->id.us++;
+ psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_CHILD);
}
static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value)
{
@@ -950,7 +887,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "disp");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Display", "Percentage of particles to display in 3d view");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
prop= RNA_def_property(srna, "material", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "omat");
@@ -1487,9 +1424,14 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
- /* animation here? */
- rna_def_animdata_common(srna);
+
+#if 0
+ prop= RNA_def_property(srna, "ipo", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ipo");
+ RNA_def_property_struct_type(prop, "Ipo");
+ RNA_def_property_ui_text(prop, "Ipo", "");
+#endif
// struct PartDeflect *pd;
// struct PartDeflect *pd2;
@@ -1510,15 +1452,9 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
- /* access to particle settings is redirected through functions */
- /* to allow proper id-buttons functionality */
prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL);
- //RNA_def_property_pointer_sdna(prop, NULL, "part");
- RNA_def_property_struct_type(prop, "ParticleSettings");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_pointer_funcs(prop, "rna_particle_settings_get", "rna_particle_settings_set", NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "part");
RNA_def_property_ui_text(prop, "Settings", "Particle system settings.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "particles", "totpart");
@@ -1733,14 +1669,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
RNA_def_property_struct_type(prop, "PointCache");
RNA_def_property_ui_text(prop, "Point Cache", "");
-
- /* offset ob */
- prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "parent");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Parent", "Use this object's coordinate system instead of global coordinate system.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
}
void RNA_def_particle(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index b8863540bdf..54cf1dea0ac 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_pose.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index a840552b86f..a0a5c41b19c 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_property.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_radio.c b/source/blender/makesrna/intern/rna_radio.c
new file mode 100644
index 00000000000..8b862b4c535
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_radio.c
@@ -0,0 +1,140 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Blender Foundation (2008).
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "rna_internal.h"
+
+#include "DNA_radio_types.h"
+
+#ifdef RNA_RUNTIME
+
+#else
+
+void RNA_def_radio(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ static EnumPropertyItem prop_drawtype_items[] = {
+ {RAD_WIREFRAME, "WIREFRAME", 0, "Wireframe", "Enables Wireframe draw mode"},
+ {RAD_SOLID, "SOLID", 0, "Solid", "Enables Solid draw mode"},
+ {RAD_GOURAUD, "GOURAUD", 0, "Gouraud", "Enables Gouraud draw mode"},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna= RNA_def_struct(brna, "Radiosity", NULL);
+ RNA_def_struct_ui_text(srna, "Radiosity", "Settings for radiosity simulation of indirect diffuse lighting.");
+ RNA_def_struct_sdna(srna, "Radio");
+
+ /* Enums */
+ prop= RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "drawtype");
+ RNA_def_property_enum_items(prop, prop_drawtype_items);
+ RNA_def_property_ui_text(prop, "Draw Mode", "Radiosity draw modes.");
+
+ /* Number values */
+ prop= RNA_def_property(srna, "hemi_resolution", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "hemires");
+ RNA_def_property_range(prop, 100, 1000);
+ RNA_def_property_ui_text(prop, "Hemi Resolution", "Sets the size of a hemicube.");
+
+ prop= RNA_def_property(srna, "max_iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "maxiter");
+ RNA_def_property_range(prop, 0, 10000);
+ RNA_def_property_ui_text(prop, "Max Iterations", "Limits the maximum number of radiosity rounds.");
+
+ prop= RNA_def_property(srna, "multiplier", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "radfac");
+ RNA_def_property_range(prop, 0.001f, 250.0f);
+ RNA_def_property_ui_text(prop, "Multiplier", "Multiplies the energy values.");
+
+ prop= RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "gamma");
+ RNA_def_property_range(prop, 0.2f, 10.0f);
+ RNA_def_property_ui_text(prop, "Gamma", "Changes the contrast of the energy values.");
+
+ prop= RNA_def_property(srna, "convergence", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "convergence");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Convergence", "Sets the lower threshold of unshot energy.");
+
+ prop= RNA_def_property(srna, "element_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "elma");
+ RNA_def_property_range(prop, 1, 500);
+ RNA_def_property_ui_text(prop, "Element Max", "Sets maximum size of an element");
+
+ prop= RNA_def_property(srna, "element_min", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "elmi");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_text(prop, "Element Min", "Sets minimum size of an element");
+
+ prop= RNA_def_property(srna, "patch_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pama");
+ RNA_def_property_range(prop, 10, 1000);
+ RNA_def_property_ui_text(prop, "Patch Max", "Sets maximum size of a patch.");
+
+ prop= RNA_def_property(srna, "patch_min", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pami");
+ RNA_def_property_range(prop, 10, 1000);
+ RNA_def_property_ui_text(prop, "Patch Min", "Sets minimum size of a patch.");
+
+ prop= RNA_def_property(srna, "subshoot_patch", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "subshootp");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_text(prop, "SubShoot Patch", "Sets the number of times the environment is tested to detect paths.");
+
+ prop= RNA_def_property(srna, "subshoot_element", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "subshoote");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_text(prop, "SubShoot Element", "Sets the number of times the environment is tested to detect elements.");
+
+ prop= RNA_def_property(srna, "max_elements", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "maxnode");
+ RNA_def_property_range(prop, 1, 250000);
+ RNA_def_property_ui_text(prop, "Max Elements", "Sets the maximum allowed number of elements.");
+
+ prop= RNA_def_property(srna, "max_subdiv_shoot", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "maxsublamp");
+ RNA_def_property_range(prop, 1, 250);
+ RNA_def_property_ui_text(prop, "Max Subdiv Shoot", "Sets the maximum number of initial shoot patches that are evaluated");
+
+ prop= RNA_def_property(srna, "remove_doubles_limit", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "nodelim");
+ RNA_def_property_range(prop, 0, 50);
+ RNA_def_property_ui_text(prop, "Remove Doubles Limit", "Sets the range for removing doubles");
+
+ /* flag */
+ prop= RNA_def_property(srna, "show_limits", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RAD_SHOWLIMITS);
+ RNA_def_property_ui_text(prop, "Show Limits", "Draws patch and element limits");
+
+ prop= RNA_def_property(srna, "show_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RAD_SHOWZ);
+ RNA_def_property_ui_text(prop, "Show Z", "Draws limits differently");
+}
+
+#endif
+
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 14db8ea3377..5066654434e 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_rna.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -309,16 +309,14 @@ PointerRNA rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key
}
} while((srna=srna->base));
- if(ptr->data) {
- group= RNA_struct_idproperties(ptr, 0);
+ group= RNA_struct_idproperties(ptr, 0);
- if(group) {
- for(idp=group->data.group.first; idp; idp=idp->next) {
- if(strcmp(idp->name, key) == 0) {
- propptr.type= &RNA_Property;
- propptr.data= idp;
- return propptr;
- }
+ if(group) {
+ for(idp=group->data.group.first; idp; idp=idp->next) {
+ if(strcmp(idp->name, key) == 0) {
+ propptr.type= &RNA_Property;
+ propptr.data= idp;
+ return propptr;
}
}
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index fd146acc6fe..875d657dee4 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_scene.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -151,34 +151,8 @@ void rna_def_tool_settings(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem uv_select_mode_items[] = {
- {UV_SELECT_VERTEX, "VERTEX", ICON_VERTEXSEL, "Vertex", "Vertex selection mode."},
- {UV_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edge", "Edge selection mode."},
- {UV_SELECT_FACE, "FACE", ICON_FACESEL, "Face", "Face selection mode."},
- {UV_SELECT_ISLAND, "ISLAND", ICON_LINKEDSEL, "Island", "Island selection mode."},
- {0, NULL, 0, NULL, NULL}};
-
- static EnumPropertyItem mesh_select_mode_items[] = {
- {SCE_SELECT_VERTEX, "VERTEX", ICON_VERTEXSEL, "Vertex", "Vertex selection mode."},
- {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edge", "Edge selection mode."},
- {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Face", "Face selection mode."},
- {0, NULL, 0, NULL, NULL}};
-
- static EnumPropertyItem snap_element_items[] = {
- {SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices."},
- {SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges."},
- {SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap to faces."},
- {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume."},
- {0, NULL, 0, NULL, NULL}};
-
- static EnumPropertyItem snap_mode_items[] = {
- {SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", "Snap closest point onto target."},
- {SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", "Snap center onto target."},
- {SCE_SNAP_TARGET_MEDIAN, "MEDIAN", 0, "Median", "Snap median onto target."},
- {SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", "Snap active onto target."},
- {0, NULL, 0, NULL, NULL}};
-
srna= RNA_def_struct(brna, "ToolSettings", NULL);
+ RNA_def_struct_nested(brna, srna, "Scene");
RNA_def_struct_ui_text(srna, "Tool Settings", "");
prop= RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
@@ -189,62 +163,6 @@ void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "VPaint");
RNA_def_property_ui_text(prop, "Vertex Paint", "");
- /* Transform */
- prop= RNA_def_property(srna, "proportional_editing", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "proportional", 0);
- RNA_def_property_ui_text(prop, "Proportional Editing", "Proportional editing mode.");
-
- prop= RNA_def_property(srna, "proportional_editing_falloff", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "prop_mode");
- RNA_def_property_enum_items(prop, prop_mode_items);
- RNA_def_property_ui_text(prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
-
- prop= RNA_def_property(srna, "snap", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP);
- RNA_def_property_ui_text(prop, "Snap", "Snap while Ctrl is held during transform.");
- RNA_def_property_ui_icon(prop, ICON_SNAP_GEAR, 1);
-
- prop= RNA_def_property(srna, "snap_align_rotation", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ROTATE);
- RNA_def_property_ui_text(prop, "Snap Align Rotation", "Align rotation with the snapping target.");
- RNA_def_property_ui_icon(prop, ICON_SNAP_NORMAL, 0);
-
- prop= RNA_def_property(srna, "snap_element", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "snap_mode");
- RNA_def_property_enum_items(prop, snap_element_items);
- RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to.");
-
- prop= RNA_def_property(srna, "snap_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "snap_target");
- RNA_def_property_enum_items(prop, snap_mode_items);
- RNA_def_property_ui_text(prop, "Snap Mode", "Which part to snap onto the target.");
-
- prop= RNA_def_property(srna, "snap_peel_object", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_PEEL_OBJECT);
- RNA_def_property_ui_text(prop, "Snap Peel Object", "Consider objects as whole when finding volume center.");
- RNA_def_property_ui_icon(prop, ICON_SNAP_PEEL_OBJECT, 0);
-
- /* UV */
- prop= RNA_def_property(srna, "uv_selection_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "uv_selectmode");
- RNA_def_property_enum_items(prop, uv_select_mode_items);
- RNA_def_property_ui_text(prop, "UV Selection Mode", "UV selection and display mode.");
-
- prop= RNA_def_property(srna, "uv_sync_selection", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "uv_flag", UV_SYNC_SELECTION);
- RNA_def_property_ui_text(prop, "UV Sync Selection", "Keep UV and edit mode mesh selection in sync.");
- RNA_def_property_ui_icon(prop, ICON_EDIT, 0);
-
- prop= RNA_def_property(srna, "uv_local_view", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "uv_flag", UV_SHOW_SAME_IMAGE);
- RNA_def_property_ui_text(prop, "UV Local View", "Draw only faces with the currently displayed image assigned.");
-
- /* Mesh */
- prop= RNA_def_property(srna, "mesh_selection_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "selectmode");
- RNA_def_property_enum_items(prop, mesh_select_mode_items);
- RNA_def_property_ui_text(prop, "Mesh Selection Mode", "Mesh selection and display mode.");
-
rna_def_sculpt(brna);
}
@@ -934,6 +852,10 @@ void RNA_def_scene(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ static EnumPropertyItem unwrapper_items[] = {
+ {0, "CONFORMAL", 0, "Conformal", ""},
+ {1, "ANGLEBASED", 0, "Angle Based", ""},
+ {0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "Scene", "ID");
RNA_def_struct_ui_text(srna, "Scene", "Scene consisting objects and defining time and render related settings.");
@@ -965,6 +887,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Visible Layers", "Layers visible when rendering the scene.");
RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_layer_set");
+ prop= RNA_def_property(srna, "proportional_editing_falloff", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "prop_mode");
+ RNA_def_property_enum_items(prop, prop_mode_items);
+ RNA_def_property_ui_text(prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
+
prop= RNA_def_property(srna, "current_frame", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_int_sdna(prop, NULL, "r.cfra");
@@ -997,6 +924,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stamp Note", "User define note for the render stamping.");
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ prop= RNA_def_property(srna, "unwrapper", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "toolsettings->unwrapper");
+ RNA_def_property_enum_items(prop, unwrapper_items);
+ RNA_def_property_ui_text(prop, "Unwrapper", "Unwrap algorithm used by the Unwrap tool.");
+
prop= RNA_def_property(srna, "nodetree", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Node Tree", "Compositing node tree.");
@@ -1004,6 +936,10 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ed");
RNA_def_property_struct_type(prop, "SequenceEditor");
RNA_def_property_ui_text(prop, "Sequence Editor", "");
+
+ prop= RNA_def_property(srna, "radiosity", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "radio");
+ RNA_def_property_ui_text(prop, "Radiosity", "");
prop= RNA_def_property(srna, "keyingsets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "keyingsets", NULL);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index b7279757455..35191744f22 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_screen.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_scriptlink.c b/source/blender/makesrna/intern/rna_scriptlink.c
index b486cd4a874..db33e7a8543 100644
--- a/source/blender/makesrna/intern/rna_scriptlink.c
+++ b/source/blender/makesrna/intern/rna_scriptlink.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_scriptlink.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 53bd230870f..d31ec7b9b83 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_sensor.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_sequence.c b/source/blender/makesrna/intern/rna_sequence.c
index 055e67fb135..5b76db4ff43 100644
--- a/source/blender/makesrna/intern/rna_sequence.c
+++ b/source/blender/makesrna/intern/rna_sequence.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_sequence.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index 363a5595b43..f26024f7a9e 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_sound.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index d5ac0d6e427..12f0c110ea2 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_space.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -246,10 +246,19 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+#if 0
+ static EnumPropertyItem select_mode_items[] = {
+ {SI_SELECT_VERTEX, "VERTEX", 0, "Vertex", "Vertex selection mode."},
+ //{SI_SELECT_EDGE, "Edge", 0, "Edge", "Edge selection mode."},
+ {SI_SELECT_FACE, "FACE", 0, "Face", "Face selection mode."},
+ {SI_SELECT_ISLAND, "ISLAND", 0, "Island", "Island selection mode."},
+ {0, NULL, 0, NULL, NULL}};
+#endif
+
static EnumPropertyItem sticky_mode_items[] = {
- {SI_STICKY_DISABLE, "DISABLED", ICON_STICKY_UVS_DISABLE, "Disabled", "Sticky vertex selection disabled."},
- {SI_STICKY_LOC, "SHARED_LOCATION", ICON_STICKY_UVS_LOC, "SHARED_LOCATION", "Select UVs that are at the same location and share a mesh vertex."},
- {SI_STICKY_VERTEX, "SHARED_VERTEX", ICON_STICKY_UVS_VERT, "SHARED_VERTEX", "Select UVs that share mesh vertex, irrespective if they are in the same location."},
+ {SI_STICKY_DISABLE, "DISABLED", 0, "Disabled", "Sticky vertex selection disabled."},
+ {SI_STICKY_LOC, "SHARED_LOCATION", 0, "SHARED_LOCATION", "Select UVs that are at the same location and share a mesh vertex."},
+ {SI_STICKY_VERTEX, "SHARED_VERTEX", 0, "SHARED_VERTEX", "Select UVs that share mesh vertex, irrespective if they are in the same location."},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem dt_uv_items[] = {
@@ -264,18 +273,17 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
{SI_UVDT_STRETCH_AREA, "AREA", 0, "Area", "Area distortion between UV and 3D faces."},
{0, NULL, 0, NULL, NULL}};
- static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
- {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
- {0, NULL, 0, NULL, NULL}};
-
srna= RNA_def_struct(brna, "SpaceUVEditor", NULL);
RNA_def_struct_sdna(srna, "SpaceImage");
RNA_def_struct_nested(brna, srna, "SpaceImageEditor");
RNA_def_struct_ui_text(srna, "Space UV Editor", "UV editor data for the image editor space.");
/* selection */
+ /*prop= RNA_def_property(srna, "selection_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "selectmode");
+ RNA_def_property_enum_items(prop, select_mode_items);
+ RNA_def_property_ui_text(prop, "Selection Mode", "UV selection and display mode.");*/
+
prop= RNA_def_property(srna, "sticky_selection_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "sticky");
RNA_def_property_enum_items(prop, sticky_mode_items);
@@ -305,15 +313,16 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Stretch Type", "Type of stretch to draw.");
RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
- prop= RNA_def_property(srna, "draw_modified_edges", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAWSHADOW);
- RNA_def_property_ui_text(prop, "Draw Modified Edges", "Draw edges after modifiers are applied.");
+ prop= RNA_def_property(srna, "draw_modified_edges", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "dt_uvstretch");
+ RNA_def_property_enum_items(prop, dt_uvstretch_items);
+ RNA_def_property_ui_text(prop, "Draw Modified Edges", "Draw edges from the final mesh after object modifier evaluation.");
RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
- prop= RNA_def_property(srna, "draw_other_objects", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_OTHER);
- RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
+ /*prop= RNA_def_property(srna, "local_view", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_LOCAL_UV);
+ RNA_def_property_ui_text(prop, "Local View", "Draw only faces with the currently displayed image assigned.");
+ RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);*/
prop= RNA_def_property(srna, "normalized_coordinates", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS);
@@ -322,6 +331,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
/* todo: move edge and face drawing options here from G.f */
+ /* editing */
+ /*prop= RNA_def_property(srna, "sync_selection", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_SYNC_UVSEL);
+ RNA_def_property_ui_text(prop, "Sync Selection", "Keep UV and edit mode mesh selection in sync.");
+ RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);*/
+
prop= RNA_def_property(srna, "snap_to_pixels", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_PIXELSNAP);
RNA_def_property_ui_text(prop, "Snap to Pixels", "Snap UVs to pixel locations while editing.");
@@ -333,12 +348,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
prop= RNA_def_property(srna, "live_unwrap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_LIVE_UNWRAP);
RNA_def_property_ui_text(prop, "Live Unwrap", "Continuously unwrap the selected UV island while transforming pinned vertices.");
-
- prop= RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "around");
- RNA_def_property_enum_items(prop, pivot_items);
- RNA_def_property_ui_text(prop, "Pivot", "Rotation/Scaling Pivot.");
- RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
}
static void rna_def_space_outliner(BlenderRNA *brna)
@@ -566,17 +575,18 @@ static void rna_def_space_buttons(BlenderRNA *brna)
PropertyRNA *prop;
static EnumPropertyItem buttons_context_items[] = {
- {BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"},
- {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
- {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
- {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraint", "Constraint"},
- {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifier", "Modifier"},
- {BCONTEXT_DATA, "DATA", 0, "Data", "Data"},
- {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"},
- {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"},
- {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"},
- {BCONTEXT_PARTICLE, "PARTICLE", ICON_PARTICLES, "Particle", "Particle"},
- {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"},
+ {BCONTEXT_SCENE, "SCENE", 0, "Scene", ""},
+ {BCONTEXT_WORLD, "WORLD", 0, "World", ""},
+ {BCONTEXT_OBJECT, "OBJECT", 0, "Object", ""},
+ {BCONTEXT_DATA, "DATA", 0, "Data", ""},
+ {BCONTEXT_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {BCONTEXT_TEXTURE, "TEXTURE", 0, "Texture", ""},
+ {BCONTEXT_PARTICLE, "PARTICLE", 0, "Particle", ""},
+ {BCONTEXT_PHYSICS, "PHYSICS", 0, "Physics", ""},
+ {BCONTEXT_GAME, "GAME", 0, "Game", ""},
+ {BCONTEXT_BONE, "BONE", 0, "Bone", ""},
+ {BCONTEXT_MODIFIER, "MODIFIER", 0, "Modifier", ""},
+ {BCONTEXT_CONSTRAINT, "CONSTRAINT", 0, "Constraint", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem panel_alignment_items[] = {
@@ -592,13 +602,11 @@ static void rna_def_space_buttons(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "mainb");
RNA_def_property_enum_items(prop, buttons_context_items);
RNA_def_property_ui_text(prop, "Buttons Context", "The type of active data to display and edit in the buttons window");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
prop= RNA_def_property(srna, "panel_alignment", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, panel_alignment_items);
RNA_def_property_ui_text(prop, "Panel Alignment", "Arrangement of the panels within the buttons window");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
/* pinned data */
prop= RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index cd39c317bc5..b44c392d741 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_text.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 2a7f65e2d90..33d7c8fd6c0 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_texture.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c
index d42603e1952..deb40f85986 100644
--- a/source/blender/makesrna/intern/rna_timeline.c
+++ b/source/blender/makesrna/intern/rna_timeline.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_timeline.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 825b3711b97..976ccc670bb 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_ui.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index a4aa60775f2..d06d4d4406d 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -136,14 +136,6 @@ void RNA_api_ui_layout(StructRNA *srna)
parm= RNA_def_string(func, "value", "", 0, "", "Enum property value.");
RNA_def_property_flag(parm, PROP_REQUIRED);*/
- func= RNA_def_function(srna, "item_pointerR", "uiItemPointerR");
- api_ui_item_common(func);
- api_ui_item_rna_common(func);
- parm= RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_string(func, "search_property", "", 0, "", "Identifier of search collection property.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
func= RNA_def_function(srna, "itemO", "uiItemO");
api_ui_item_op_common(func);
@@ -197,7 +189,8 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_common(func);
func= RNA_def_function(srna, "itemM", "uiItemM");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
api_ui_item_common(func);
parm= RNA_def_string(func, "menu", "", 0, "", "Identifier of the menu.");
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -213,12 +206,15 @@ void RNA_api_ui_layout(StructRNA *srna)
/* templates */
func= RNA_def_function(srna, "template_header", "uiTemplateHeader");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
func= RNA_def_function(srna, "template_ID", "uiTemplateID");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
api_ui_item_rna_common(func);
RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
+ RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a new ID block.");
RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
@@ -249,23 +245,6 @@ void RNA_api_ui_layout(StructRNA *srna)
func= RNA_def_function(srna, "template_layers", "uiTemplateLayers");
api_ui_item_rna_common(func);
-
- func= RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- parm= RNA_def_pointer(func, "image", "Image", "", "");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_pointer(func, "image_user", "ImageUser", "", "");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "template_list", "uiTemplateList");
- api_ui_item_rna_common(func);
- parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX);
- parm= RNA_def_int(func, "columns", 5, 0, INT_MAX, "", "Number of columns to display.", 0, INT_MAX);
- parm= RNA_def_boolean(func, "compact", 0, "", "Use compact, single row list template.");
- parm= RNA_def_collection(func, "items", 0, "", "Items visible in the list.");
- RNA_def_function_return(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 609082144e1..ad3875280fb 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_userdef.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -139,12 +139,7 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
prop= RNA_def_property(srna, "kerning", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, -5.0, 5.0);
- RNA_def_property_ui_text(prop, "Kerning", "User kerning value in pixels");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
-
- prop= RNA_def_property(srna, "overlap", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "overlap", 1);
- RNA_def_property_ui_text(prop, "Overlap", "Check for overlap characters");
+ RNA_def_property_ui_text(prop, "Kerning", "");
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop= RNA_def_property(srna, "shadow", PROP_INT, PROP_NONE);
@@ -306,12 +301,6 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ThemeWidgetColors");
RNA_def_property_ui_text(prop, "Option Widget Colors", "");
RNA_def_property_update(prop, NC_WINDOW, NULL);
-
- prop= RNA_def_property(srna, "wcol_toggle", PROP_POINTER, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "wcol_toggle");
- RNA_def_property_struct_type(prop, "ThemeWidgetColors");
- RNA_def_property_ui_text(prop, "Toggle Widget Colors", "");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
prop= RNA_def_property(srna, "wcol_num", PROP_POINTER, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "wcol_num");
@@ -354,12 +343,7 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ThemeWidgetColors");
RNA_def_property_ui_text(prop, "Menu Item Colors", "");
RNA_def_property_update(prop, NC_WINDOW, NULL);
-
- prop= RNA_def_property(srna, "wcol_scroll", PROP_POINTER, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "wcol_scroll");
- RNA_def_property_struct_type(prop, "ThemeWidgetColors");
- RNA_def_property_ui_text(prop, "Scroll Widget Colors", "");
- RNA_def_property_update(prop, NC_WINDOW, NULL);
+
prop= RNA_def_property(srna, "icon_file", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "iconfile");
@@ -1521,7 +1505,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Toolbox Column Layout", "Use a column layout for toolbox.");
prop= RNA_def_property(srna, "directional_menus", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DIRECTIONALORDER);
RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
/* snap to grid */
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index aa2aaaf6342..7837a0b5657 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_vfont.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_vpaint.c b/source/blender/makesrna/intern/rna_vpaint.c
index a34099dffb7..6a831467487 100644
--- a/source/blender/makesrna/intern/rna_vpaint.c
+++ b/source/blender/makesrna/intern/rna_vpaint.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_vpaint.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 1bfc3b6f8f6..3cb3f4ee4cb 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_wm.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -30,120 +30,6 @@
#include "rna_internal.h"
#include "DNA_windowmanager_types.h"
-#include "WM_types.h" /* wmEvent */
-
-
-EnumPropertyItem event_value_items[] = {
- {KM_ANY, "ANY", 0, "Any", ""},
- {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
- {KM_PRESS, "PRESS", 0, "Press", ""},
- {KM_RELEASE, "RELEASE", 0, "Release", ""},
- {0, NULL, 0, NULL, NULL}};
-
-/* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */
-EnumPropertyItem event_type_items[] = {
- {AKEY, "A", 0, "A", ""},
- {BKEY, "B", 0, "B", ""},
- {CKEY, "C", 0, "C", ""},
- {DKEY, "D", 0, "D", ""},
- {EKEY, "E", 0, "E", ""},
- {FKEY, "F", 0, "F", ""},
- {GKEY, "G", 0, "G", ""},
- {HKEY, "H", 0, "H", ""},
- {IKEY, "I", 0, "I", ""},
- {JKEY, "J", 0, "J", ""},
- {KKEY, "K", 0, "K", ""},
- {LKEY, "L", 0, "L", ""},
- {MKEY, "M", 0, "M", ""},
- {NKEY, "N", 0, "N", ""},
- {OKEY, "O", 0, "O", ""},
- {PKEY, "P", 0, "P", ""},
- {QKEY, "Q", 0, "Q", ""},
- {RKEY, "R", 0, "R", ""},
- {SKEY, "S", 0, "S", ""},
- {TKEY, "T", 0, "T", ""},
- {UKEY, "U", 0, "U", ""},
- {VKEY, "V", 0, "V", ""},
- {WKEY, "W", 0, "W", ""},
- {XKEY, "X", 0, "X", ""},
- {YKEY, "Y", 0, "Y", ""},
- {ZKEY, "Z", 0, "Z", ""},
-
- {ZEROKEY, "ZERO", 0, "Zero Key", ""},
- {ONEKEY, "ONE", 0, "One Key", ""},
- {TWOKEY, "TWO", 0, "Two Key", ""},
- {THREEKEY, "THREE", 0, "Three Key", ""},
- {FOURKEY, "FOUR", 0, "Four Key", ""},
- {FIVEKEY, "FIVE", 0, "Five Key", ""},
- {SIXKEY, "SIX", 0, "Six Key", ""},
- {SEVENKEY, "SEVEN", 0, "Seven Key", ""},
- {EIGHTKEY, "EIGHT", 0, "Eight Key", ""},
- {NINEKEY, "NINE", 0, "Nine Key", ""},
-
- {LEFTCTRLKEY, "LEFT_CTRL", 0, "Left Ctrl", ""},
- {LEFTALTKEY, "LEFT_ALT", 0, "Left Alt", ""},
- {RIGHTALTKEY, "RIGHT_ALT", 0, "Right Alt", ""},
- {RIGHTCTRLKEY, "RIGHT_CTRL", 0, "Rightctrl", ""},
- {RIGHTSHIFTKEY, "RIGHT_SHIFT", 0, "Rightshift", ""},
- {LEFTSHIFTKEY, "LEFT_SHIFT", 0, "Leftshift", ""},
-
- {ESCKEY, "ESC", 0, "Esc", ""},
- {TABKEY, "TAB", 0, "Tab", ""},
- {RETKEY, "RET", 0, "Return", ""},
- {SPACEKEY, "SPACE", 0, "Spacebar", ""},
- {LINEFEEDKEY, "LINE_FEED", 0, "Line Feed", ""},
- {BACKSPACEKEY, "BACK_SPACE", 0, "Back Space", ""},
- {DELKEY, "DEL", 0, "Delete", ""},
- {SEMICOLONKEY, "SEMI_COLON", 0, "Semicolon", ""},
- {PERIODKEY, "PERIOD", 0, "Period", ""},
- {COMMAKEY, "COMMA", 0, "Comma", ""},
- {QUOTEKEY, "QUOTE", 0, "Quote", ""},
- {ACCENTGRAVEKEY, "ACCENT_GRAVE", 0, "Accentgrave", ""},
- {MINUSKEY, "MINUS", 0, "Minus", ""},
- {SLASHKEY, "SLASH", 0, "Slash", ""},
- {BACKSLASHKEY, "BACK_SLASH", 0, "Backslash", ""},
- {EQUALKEY, "EQUAL", 0, "Equal", ""},
- {LEFTBRACKETKEY, "LEFT_BRACKET", 0, "Leftbracket", ""},
- {RIGHTBRACKETKEY, "RIGHT_BRACKET", 0, "Rightbracket", ""},
- {LEFTARROWKEY, "LEFT_ARROW", 0, "Left Arrow", ""},
- {DOWNARROWKEY, "DOWN_ARROW", 0, "Down Arrow", ""},
- {RIGHTARROWKEY, "RIGHT_ARROW", 0, "Right Arrow", ""},
- {UPARROWKEY, "UP_ARROW", 0, "Up Arrow", ""},
- {PAD2, "NUMPAD_2", 0, "Numpad 2", ""},
- {PAD4, "NUMPAD_4", 0, "Numpad 4", ""},
- {PAD6, "NUMPAD_6", 0, "Numpad 6", ""},
- {PAD8, "NUMPAD_8", 0, "Numpad 8", ""},
- {PAD1, "NUMPAD_1", 0, "Numpad 1", ""},
- {PAD3, "NUMPAD_3", 0, "Numpad 3", ""},
- {PAD5, "NUMPAD_5", 0, "Numpad 5", ""},
- {PAD7, "NUMPAD_7", 0, "Numpad 7", ""},
- {PAD9, "NUMPAD_9", 0, "Numpad 9", ""},
- {PADPERIOD, "NUMPAD_PERIOD", 0, "Numpad .", ""},
- {PADSLASHKEY, "NUMPAD_SLASH", 0, "Numpad /", ""},
- {PADASTERKEY, "NUMPAD_ASTERIX", 0, "Numpad *", ""},
- {PAD0, "NUMPAD_0", 0, "Numpad 0", ""},
- {PADMINUS, "NUMPAD_MINUS", 0, "Numpad -", ""},
- {PADENTER, "NUMPAD_ENTER", 0, "Numpad Enter", ""},
- {PADPLUSKEY, "NUMPAD_PLUS", 0, "Numpad +", ""},
- {F1KEY, "F1", 0, "F1", ""},
- {F2KEY, "F2", 0, "F2", ""},
- {F3KEY, "F3", 0, "F3", ""},
- {F4KEY, "F4", 0, "F4", ""},
- {F5KEY, "F5", 0, "F5", ""},
- {F6KEY, "F6", 0, "F6", ""},
- {F7KEY, "F7", 0, "F7", ""},
- {F8KEY, "F8", 0, "F8", ""},
- {F9KEY, "F9", 0, "F9", ""},
- {F10KEY, "F10", 0, "F10", ""},
- {F11KEY, "F11", 0, "F11", ""},
- {F12KEY, "F12", 0, "F12", ""},
- {PAUSEKEY, "PAUSE", 0, "Pause", ""},
- {INSERTKEY, "INSERT", 0, "Insert", ""},
- {HOMEKEY, "HOME", 0, "Home", ""},
- {PAGEUPKEY, "PAGE_UP", 0, "Page Up", ""},
- {PAGEDOWNKEY, "PAGE_DOWN", 0, "Page Down", ""},
- {ENDKEY, "END", 0, "End", ""},
- {0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
@@ -201,20 +87,6 @@ static PointerRNA rna_Operator_properties_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_OperatorProperties, op->properties);
}
-
-static void rna_Event_ascii_get(PointerRNA *ptr, char *value)
-{
- wmEvent *event= (wmEvent*)ptr->id.data;
- value[0]= event->ascii;
- value[1]= '\0';
-}
-
-static int rna_Event_ascii_length(PointerRNA *ptr)
-{
- wmEvent *event= (wmEvent*)ptr->id.data;
- return (event->ascii)? 1 : 0;
-}
-
#else
static void rna_def_operator(BlenderRNA *brna)
@@ -274,80 +146,7 @@ static void rna_def_operator_filelist_element(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Name", "the name of a file or directory within a file list");
}
-
-static void rna_def_event(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna= RNA_def_struct(brna, "Event", NULL);
- RNA_def_struct_ui_text(srna, "Event", "Window Manager Event");
- RNA_def_struct_sdna(srna, "wmEvent");
-
- /* strings */
- prop= RNA_def_property(srna, "ascii", PROP_STRING, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_string_funcs(prop, "rna_Event_ascii_get", "rna_Event_ascii_length", NULL);
- RNA_def_property_ui_text(prop, "ASCII", "Single ASCII character for this event.");
-
-
- /* enums */
- prop= RNA_def_property(srna, "value", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "val");
- RNA_def_property_enum_items(prop, event_value_items);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Value", "The type of event, only applies to some.");
-
- prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, event_type_items);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Type", "");
-
-
- /* mouse */
- prop= RNA_def_property(srna, "mouse_x", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "x");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Mouse X Position", "The window relative vertical location of the mouse.");
-
- prop= RNA_def_property(srna, "mouse_y", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "y");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Mouse Y Position", "The window relative horizontal location of the mouse.");
-
- prop= RNA_def_property(srna, "mouse_prev_x", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "prevx");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Mouse Previous X Position", "The window relative vertical location of the mouse.");
-
- prop= RNA_def_property(srna, "mouse_prev_y", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "prevy");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Mouse Previous Y Position", "The window relative horizontal location of the mouse.");
-
- /* modifiers */
- prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shift", 1);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Shift", "True when the shift key is held.");
-
- prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 1);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Ctrl", "True when the shift key is held.");
-
- prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "alt", 1);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Alt", "True when the shift key is held.");
-
- prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "oskey", 1);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "OS Key", "True when the shift key is held.");
-}
static void rna_def_windowmanager(BlenderRNA *brna)
{
@@ -370,7 +169,6 @@ void RNA_def_wm(BlenderRNA *brna)
rna_def_operator(brna);
rna_def_operator_utils(brna);
rna_def_operator_filelist_element(brna);
- rna_def_event(brna);
rna_def_windowmanager(brna);
}
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index fd34d7c4d70..87a94993a42 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_wm_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index f5eb81e3cea..e313f01c194 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_world.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -337,7 +337,7 @@ void RNA_def_world(BlenderRNA *brna)
static EnumPropertyItem physics_engine_items[] = {
{WOPHY_NONE, "NONE", 0, "None", ""},
//{WOPHY_ENJI, "ENJI", 0, "Enji", ""},
- //{WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""},
+ {WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""},
//{WOPHY_DYNAMO, "DYNAMO", 0, "Dynamo", ""},
//{WOPHY_ODE, "ODE", 0, "ODE", ""},
{WOPHY_BULLET, "BULLET", 0, "Bullet", ""},
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index d141a585378..855fdde50c5 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BPY_extern.h 12334 2007-10-21 23:00:29Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -50,8 +50,6 @@ struct bConstraintTarget; /* DNA_constraint_types.h*/
struct Script; /* DNA_screen_types.h */
struct BPyMenu;
struct bContext;
-struct ReportList;
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
new file mode 100644
index 00000000000..b67f1e717da
--- /dev/null
+++ b/source/blender/python/BPY_menus.c
@@ -0,0 +1,1118 @@
+/*
+ * $Id: BPY_menus.c 12932 2007-12-17 20:21:06Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Michael Reimpell
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+/*
+ *This is the main file responsible for having bpython scripts accessible
+ * from Blender menus. To know more, please start with its header file.
+ */
+
+#include "BPY_menus.h"
+
+#include <Python.h>
+#ifndef WIN32
+ #include <dirent.h>
+#else
+ #include "BLI_winstuff.h"
+#endif
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+#include "DNA_userdef_types.h" /* for U.pythondir */
+#include "api2_2x/EXPP_interface.h" /* for bpy_gethome() */
+
+#define BPYMENU_DATAFILE "Bpymenus"
+#define MAX_DIR_DEPTH 4 /* max depth for traversing scripts dirs */
+#define MAX_DIR_NUMBER 30 /* max number of dirs in scripts dirs trees */
+
+static int DEBUG;
+static int Dir_Depth;
+static int Dirs_Number;
+
+/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
+ * where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
+*/
+BPyMenu *BPyMenuTable[PYMENU_TOTAL];
+
+static int bpymenu_group_atoi( char *str )
+{
+ if( !strcmp( str, "Export" ) )
+ return PYMENU_EXPORT;
+ else if( !strcmp( str, "Import" ) )
+ return PYMENU_IMPORT;
+ else if( !strcmp( str, "Help" ) )
+ return PYMENU_HELP;
+ else if( !strcmp( str, "HelpWebsites" ) )
+ return PYMENU_HELPWEBSITES;
+ else if( !strcmp( str, "HelpSystem" ) )
+ return PYMENU_HELPSYSTEM;
+ else if( !strcmp( str, "Render" ) )
+ return PYMENU_RENDER;
+ else if( !strcmp( str, "System" ) )
+ return PYMENU_SYSTEM;
+ else if( !strcmp( str, "Object" ) )
+ return PYMENU_OBJECT;
+ else if( !strcmp( str, "Mesh" ) )
+ return PYMENU_MESH;
+ else if( !strncmp( str, "Theme", 5 ) )
+ return PYMENU_THEMES;
+ else if( !strcmp( str, "Add" ) )
+ return PYMENU_ADD;
+ else if( !strcmp( str, "Wizards" ) )
+ return PYMENU_WIZARDS;
+ else if( !strcmp( str, "Animation" ) )
+ return PYMENU_ANIMATION;
+ else if( !strcmp( str, "Materials" ) )
+ return PYMENU_MATERIALS;
+ else if( !strcmp( str, "UV" ) )
+ return PYMENU_UV;
+ else if( !strcmp( str, "Image" ) )
+ return PYMENU_IMAGE;
+ else if( !strcmp( str, "FaceSelect" ) )
+ return PYMENU_FACESELECT;
+ else if( !strcmp( str, "WeightPaint" ) )
+ return PYMENU_WEIGHTPAINT;
+ else if( !strcmp( str, "VertexPaint" ) )
+ return PYMENU_VERTEXPAINT;
+ else if( !strcmp( str, "UVCalculation" ) )
+ return PYMENU_UVCALCULATION;
+ else if( !strcmp( str, "Armature" ) )
+ return PYMENU_ARMATURE;
+ else if( !strcmp( str, "ScriptTemplate" ) )
+ return PYMENU_SCRIPTTEMPLATE;
+ else if( !strcmp( str, "MeshFaceKey" ) )
+ return PYMENU_MESHFACEKEY;
+ else if( !strcmp( str, "AddMesh" ) )
+ return PYMENU_ADDMESH;
+ /* "Misc" or an inexistent group name: use misc */
+ else
+ return PYMENU_MISC;
+}
+
+char *BPyMenu_group_itoa( short menugroup )
+{
+ switch ( menugroup ) {
+ case PYMENU_EXPORT:
+ return "Export";
+ break;
+ case PYMENU_IMPORT:
+ return "Import";
+ break;
+ case PYMENU_ADD:
+ return "Add";
+ break;
+ case PYMENU_HELP:
+ return "Help";
+ break;
+ case PYMENU_HELPWEBSITES:
+ return "HelpWebsites";
+ break;
+ case PYMENU_HELPSYSTEM:
+ return "HelpSystem";
+ break;
+ case PYMENU_RENDER:
+ return "Render";
+ break;
+ case PYMENU_SYSTEM:
+ return "System";
+ break;
+ case PYMENU_OBJECT:
+ return "Object";
+ break;
+ case PYMENU_MESH:
+ return "Mesh";
+ break;
+ case PYMENU_THEMES:
+ return "Themes";
+ break;
+ case PYMENU_WIZARDS:
+ return "Wizards";
+ break;
+ case PYMENU_ANIMATION:
+ return "Animation";
+ break;
+ case PYMENU_MATERIALS:
+ return "Materials";
+ break;
+ case PYMENU_UV:
+ return "UV";
+ break;
+ case PYMENU_IMAGE:
+ return "Image";
+ break;
+ case PYMENU_FACESELECT:
+ return "FaceSelect";
+ break;
+ case PYMENU_WEIGHTPAINT:
+ return "WeightPaint";
+ break;
+ case PYMENU_VERTEXPAINT:
+ return "VertexPaint";
+ break;
+ case PYMENU_UVCALCULATION:
+ return "UVCalculation";
+ break;
+ case PYMENU_ARMATURE:
+ return "Armature";
+ break;
+ case PYMENU_SCRIPTTEMPLATE:
+ return "ScriptTemplate";
+ break;
+ case PYMENU_MESHFACEKEY:
+ return "MeshFaceKey";
+ break;
+ case PYMENU_ADDMESH:
+ return "AddMesh";
+ break;
+ case PYMENU_MISC:
+ return "Misc";
+ break;
+ }
+ return NULL;
+}
+
+/* BPyMenu_CreatePupmenuStr:
+ * build and return a meaninful string to be used by pupmenu(). The
+ * string is made of a bpymenu name as title and its submenus as possible
+ * choices for the user.
+*/
+char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short menugroup )
+{
+ BPySubMenu *pysm = pym->submenus;
+ char str[1024], str2[100];
+ int i = 0, rlen;
+
+ if( !pym || !pysm )
+ return NULL;
+
+ str[0] = '\0';
+
+ PyOS_snprintf( str2, sizeof( str2 ), "%s: %s%%t",
+ BPyMenu_group_itoa( menugroup ), pym->name );
+ strcat( str, str2 );
+
+ while( pysm ) {
+ PyOS_snprintf( str2, sizeof( str2 ), "|%s%%x%d", pysm->name,
+ i );
+ rlen = sizeof( str ) - strlen( str );
+ strncat( str, str2, rlen );
+ i++;
+ pysm = pysm->next;
+ }
+
+ return BLI_strdup( str );
+}
+
+static void bpymenu_RemoveAllSubEntries( BPySubMenu * smenu )
+{
+ BPySubMenu *tmp;
+
+ while( smenu ) {
+ tmp = smenu->next;
+ if( smenu->name )
+ MEM_freeN( smenu->name );
+ if( smenu->arg )
+ MEM_freeN( smenu->arg );
+ MEM_freeN( smenu );
+ smenu = tmp;
+ }
+ return;
+}
+
+void BPyMenu_RemoveAllEntries( void )
+{
+ BPyMenu *tmp, *pymenu;
+ int i;
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ while( pymenu ) {
+ tmp = pymenu->next;
+ if( pymenu->name )
+ MEM_freeN( pymenu->name );
+ if( pymenu->filename )
+ MEM_freeN( pymenu->filename );
+ if( pymenu->tooltip )
+ MEM_freeN( pymenu->tooltip );
+ if( pymenu->submenus )
+ bpymenu_RemoveAllSubEntries( pymenu->
+ submenus );
+ MEM_freeN( pymenu );
+ pymenu = tmp;
+ }
+ BPyMenuTable[i] = NULL;
+ }
+
+ Dirs_Number = 0;
+ Dir_Depth = 0;
+
+ return;
+}
+
+static BPyMenu *bpymenu_FindEntry( short group, char *name )
+{
+ BPyMenu *pymenu;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+
+ pymenu = BPyMenuTable[group];
+
+ while( pymenu ) {
+ if( !strcmp( pymenu->name, name ) )
+ return pymenu;
+ pymenu = pymenu->next;
+ }
+
+ return NULL;
+}
+
+/* BPyMenu_GetEntry:
+ * given a group and a position, return the entry in that position from
+ * that group.
+*/
+BPyMenu *BPyMenu_GetEntry( short group, short pos )
+{
+ BPyMenu *pym = NULL;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+
+ pym = BPyMenuTable[group];
+
+ while( pos-- ) {
+ if( pym )
+ pym = pym->next;
+ else
+ break;
+ }
+
+ return pym; /* found entry or NULL */
+}
+
+static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip )
+{
+ if( !pymenu )
+ return;
+
+ if( pymenu->tooltip )
+ MEM_freeN( pymenu->tooltip );
+ pymenu->tooltip = BLI_strdup( tip );
+
+ return;
+}
+
+/* bpymenu_AddEntry:
+ * try to find an existing pymenu entry with the given type and name;
+ * if found, update it with new info, otherwise create a new one and fill it.
+ */
+static BPyMenu *bpymenu_AddEntry( short group, short version, char *name,
+ char *fname, int is_userdir, char *tooltip )
+{
+ BPyMenu *menu, *next = NULL, **iter;
+ int nameclash = 0;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+ if( !name || !fname )
+ return NULL;
+
+ menu = bpymenu_FindEntry( group, name ); /* already exists? */
+
+ /* if a menu with this name already exists in the same group:
+ * - if one script is in the default dir and the other in U.pythondir,
+ * accept and let the new one override the other.
+ * - otherwise, report the error and return NULL. */
+ if( menu ) {
+ if( menu->dir < is_userdir ) { /* new one is in U.pythondir */
+ nameclash = 1;
+ if( menu->name )
+ MEM_freeN( menu->name );
+ if( menu->filename )
+ MEM_freeN( menu->filename );
+ if( menu->tooltip )
+ MEM_freeN( menu->tooltip );
+ if( menu->submenus )
+ bpymenu_RemoveAllSubEntries( menu->submenus );
+ next = menu->next;
+ } else { /* they are in the same dir */
+ if (DEBUG) {
+ fprintf(stderr, "\n\
+Warning: script %s's menu name is already in use.\n\
+Edit the script and change its \n\
+Name: '%s'\n\
+field, please.\n\
+Note: if you really want to have two scripts for the same menu with\n\
+the same name, keep one in the default dir and the other in\n\
+the user defined dir (only the later will be registered).\n", fname, name);
+ }
+ return NULL;
+ }
+ } else
+ menu = MEM_mallocN( sizeof( BPyMenu ), "pymenu" );
+
+ if( !menu )
+ return NULL;
+
+ menu->name = BLI_strdup( name );
+ menu->version = version;
+ menu->filename = BLI_strdup( fname );
+ menu->tooltip = NULL;
+ if( tooltip )
+ menu->tooltip = BLI_strdup( tooltip );
+ menu->dir = is_userdir;
+ menu->submenus = NULL;
+ menu->next = next; /* non-NULL if menu already existed */
+
+ if( nameclash )
+ return menu; /* no need to place it, it's already at the list */
+ else { /* insert the new entry in its correct position at the table */
+ BPyMenu *prev = NULL;
+ char *s = NULL;
+
+ iter = &BPyMenuTable[group];
+ while( *iter ) {
+ s = ( *iter )->name;
+ if( s )
+ if( strcmp( menu->name, s ) < 0 )
+ break; /* sort by names */
+ prev = *iter;
+ iter = &( ( *iter )->next );
+ }
+
+ if( *iter ) { /* prepend */
+ menu->next = *iter;
+ if( prev )
+ prev->next = menu;
+ else
+ BPyMenuTable[group] = menu; /* is first entry */
+ } else
+ *iter = menu; /* append */
+ }
+
+ return menu;
+}
+
+/* bpymenu_AddSubEntry:
+ * add a submenu to an existing python menu.
+ */
+static int bpymenu_AddSubEntry( BPyMenu * mentry, char *name, char *arg )
+{
+ BPySubMenu *smenu, **iter;
+
+ smenu = MEM_mallocN( sizeof( BPySubMenu ), "pysubmenu" );
+ if( !smenu )
+ return -1;
+
+ smenu->name = BLI_strdup( name );
+ smenu->arg = BLI_strdup( arg );
+ smenu->next = NULL;
+
+ if( !smenu->name || !smenu->arg )
+ return -1;
+
+ iter = &( mentry->submenus );
+ while( *iter )
+ iter = &( ( *iter )->next );
+
+ *iter = smenu;
+
+ return 0;
+}
+
+/* bpymenu_CreateFromFile:
+ * parse the bpymenus data file where Python menu data is stored;
+ * based on this data, create and fill the pymenu structs.
+ */
+static int bpymenu_CreateFromFile( void )
+{
+ FILE *fp;
+ char line[255], w1[255], w2[255], tooltip[255], *tip;
+ char *homedir = NULL;
+ int parsing, version, is_userdir;
+ short group;
+ BPyMenu *pymenu = NULL;
+
+ /* init global bpymenu table (it is a list of pointers to struct BPyMenus
+ * for each available cathegory: import, export, etc.) */
+ for( group = 0; group < PYMENU_TOTAL; group++ )
+ BPyMenuTable[group] = NULL;
+
+ /* let's try to open the file with bpymenu data */
+ homedir = bpy_gethome(0);
+ if (!homedir) {
+ if( DEBUG )
+ fprintf(stderr,
+ "BPyMenus error: couldn't open config file Bpymenus: no home dir.\n");
+ return -1;
+ }
+
+ BLI_make_file_string( "/", line, homedir, BPYMENU_DATAFILE );
+
+ fp = fopen( line, "rb" );
+
+ if( !fp ) {
+ if( DEBUG )
+ fprintf(stderr, "BPyMenus error: couldn't open config file %s.\n", line );
+ return -1;
+ }
+
+ fgets( line, 255, fp ); /* header */
+
+ /* check if the U.pythondir we saved at the file is different from the
+ * current one. If so, return to force updating from dirs */
+ w1[0] = '\0';
+ fscanf( fp, "# User defined scripts dir: %[^\n]\n", w1 );
+ if( w1 ) {
+ char upythondir[FILE_MAXDIR];
+
+ BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ if( strcmp( w1, upythondir ) != 0 )
+ return -1;
+ w1[0] = '\0';
+ }
+
+ while( fgets( line, 255, fp ) ) { /* parsing file lines */
+
+ switch ( line[0] ) { /* check first char */
+ case '#': /* comment */
+ continue;
+ break;
+ case '\n':
+ continue;
+ break;
+ default:
+ parsing = sscanf( line, "%s {\n", w1 ); /* menu group */
+ break;
+ }
+
+ if( parsing == 1 ) { /* got menu group string */
+ group = (short)bpymenu_group_atoi( w1 );
+ if( group < 0 && DEBUG ) { /* invalid type */
+ fprintf(stderr,
+ "BPyMenus error parsing config file: wrong group: %s,\n\
+will use 'Misc'.\n", w1 );
+ }
+ } else
+ continue;
+
+ for(;;) {
+ tip = NULL; /* optional tooltip */
+ fgets( line, 255, fp );
+ if( line[0] == '}' )
+ break;
+ else if( line[0] == '\n' )
+ continue;
+ else if( line[0] == '\'' ) { /* menu entry */
+ parsing =
+ sscanf( line,
+ "'%[^']' %d %s %d '%[^']'\n",
+ w1, &version, w2, &is_userdir,
+ tooltip );
+
+ if( parsing <= 0 ) { /* invalid line, get rid of it */
+ fgets( line, 255, fp );
+ } else if( parsing == 5 )
+ tip = tooltip; /* has tooltip */
+
+ pymenu = bpymenu_AddEntry( group,
+ ( short ) version,
+ w1, w2, is_userdir,
+ tip );
+ if( !pymenu ) {
+ puts( "BPyMenus error: couldn't create bpymenu entry.\n" );
+ fclose( fp );
+ return -1;
+ }
+ } else if( line[0] == '|' && line[1] == '_' ) { /* menu sub-entry */
+ if( !pymenu )
+ continue; /* no menu yet, skip this line */
+ sscanf( line, "|_%[^:]: %s\n", w1, w2 );
+ bpymenu_AddSubEntry( pymenu, w1, w2 );
+ }
+ }
+ }
+
+ fclose( fp );
+ return 0;
+}
+
+/* bpymenu_WriteDataFile:
+ * writes the registered scripts info to the user's home dir, for faster
+ * access when the scripts dir hasn't changed.
+*/
+static void bpymenu_WriteDataFile( void )
+{
+ BPyMenu *pymenu;
+ BPySubMenu *smenu;
+ FILE *fp;
+ char fname[FILE_MAXDIR], *homedir;
+ int i;
+
+ homedir = bpy_gethome(0);
+
+ if (!homedir) {
+ if( DEBUG )
+ fprintf(stderr,
+ "BPyMenus error: couldn't write Bpymenus file: no home dir.\n\n");
+ return;
+ }
+
+ BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
+
+ fp = fopen( fname, "w" );
+ if( !fp ) {
+ if( DEBUG )
+ fprintf(stderr, "BPyMenus error: couldn't write %s file.\n\n",
+ fname );
+ return;
+ }
+
+ fprintf( fp,
+ "# Blender: registered menu entries for bpython scripts\n" );
+
+ if (U.pythondir[0] != '\0' &&
+ strcmp(U.pythondir, "/") != 0 && strcmp(U.pythondir, "//") != 0)
+ {
+ char upythondir[FILE_MAXDIR];
+
+ BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ fprintf( fp, "# User defined scripts dir: %s\n", upythondir );
+ }
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ if( !pymenu )
+ continue;
+ fprintf( fp, "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
+ while( pymenu ) {
+ fprintf( fp, "'%s' %d %s %d", pymenu->name,
+ pymenu->version, pymenu->filename,
+ pymenu->dir );
+ if( pymenu->tooltip )
+ fprintf( fp, " '%s'\n", pymenu->tooltip );
+ else
+ fprintf( fp, "\n" );
+ smenu = pymenu->submenus;
+ while( smenu ) {
+ fprintf( fp, "|_%s: %s\n", smenu->name,
+ smenu->arg );
+ smenu = smenu->next;
+ }
+ pymenu = pymenu->next;
+ }
+ fprintf( fp, "}\n" );
+ }
+
+ fclose( fp );
+ return;
+}
+
+/* BPyMenu_PrintAllEntries:
+ * useful for debugging.
+ */
+void BPyMenu_PrintAllEntries( void )
+{
+ BPyMenu *pymenu;
+ BPySubMenu *smenu;
+ int i;
+
+ printf( "# Blender: registered menu entries for bpython scripts\n" );
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ printf( "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
+ while( pymenu ) {
+ printf( "'%s' %d %s %d", pymenu->name, pymenu->version,
+ pymenu->filename, pymenu->dir );
+ if( pymenu->tooltip )
+ printf( " '%s'\n", pymenu->tooltip );
+ else
+ printf( "\n" );
+ smenu = pymenu->submenus;
+ while( smenu ) {
+ printf( "|_%s: %s\n", smenu->name,
+ smenu->arg );
+ smenu = smenu->next;
+ }
+ pymenu = pymenu->next;
+ }
+ printf( "}\n" );
+ }
+}
+
+/* bpymenu_ParseFile:
+ * recursively scans folders looking for scripts to register.
+ *
+ * This function scans the scripts directory looking for .py files with the
+ * right header and menu info, using that to fill the bpymenu structs.
+ * is_userdir defines if the script is in the default scripts dir or the
+ * user defined one (U.pythondir: is_userdir == 1).
+ * Speed is important.
+ *
+ * The first line of the script must be '#!BPY'.
+ * The header registration lines must appear between the first pair of
+ * '\"\"\"' and follow this order (the single-quotes are part of
+ * the format):
+ *
+ * # \"\"\"<br>
+ * # Name: 'script name for the menu'
+ * # Blender: <code>short int</code> (minimal Blender version)
+ * # Group: 'group name' (defines menu)
+ * # Submenu: 'submenu name' related_1word_arg
+ * # Tooltip: 'tooltip for the menu'
+ * # \"\"\"
+ *
+ * Notes:
+ *
+ * - Commenting out header lines with "#" is optional, but recommended.
+ * - There may be more than one submenu line, or none:
+ * submenus and the tooltip are optional;
+ * - The Blender version is the same number reported by
+ * Blender.Get('version') in BPython or G.version in C;
+ * - Line length must be less than 99.
+ */
+static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir)
+{
+ char line[100];
+ char head[100];
+ char middle[100];
+ char tail[100];
+ int matches;
+ int parser_state;
+
+ char script_name[100];
+ int script_version = 1;
+ int script_group;
+
+ BPyMenu *scriptMenu = NULL;
+
+ if (file != NULL) {
+ parser_state = 1; /* state of parser, 0 to terminate */
+
+ while ((parser_state != 0) && (fgets(line, 100, file) != NULL)) {
+
+ switch (parser_state) {
+
+ case 1: /* !BPY */
+ if (strncmp(line, "#!BPY", 5) == 0) {
+ parser_state++;
+ } else {
+ parser_state = 0;
+ }
+ break;
+
+ case 2: /* \"\"\" */
+ if ((strstr(line, "\"\"\""))) {
+ parser_state++;
+ }
+ break;
+
+ case 3: /* Name: 'script name for the menu' */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, script_name, tail);
+ if ((matches == 3) && (strstr(head, "Name:") != NULL)) {
+ parser_state++;
+ } else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 4: /* Blender: <short int> */
+ matches = sscanf(line, "%[^1234567890]%i%c", head, &script_version,
+ tail);
+ if (matches == 3) {
+ parser_state++;
+ } else {
+ if (DEBUG)
+ fprintf(stderr,"BPyMenus error: Wrong 'Blender' line: %s\n",fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 5: /* Group: 'group name' */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((matches == 3) && (strstr(head, "Group:") != NULL)) {
+ script_group = bpymenu_group_atoi(middle);
+ if (script_group < 0) {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n",
+ middle, fname);
+ parser_state = 0;
+ }
+
+ else { /* register script */
+ scriptMenu = bpymenu_AddEntry((short)script_group,
+ (short int)script_version, script_name, fname, is_userdir,NULL);
+ if (scriptMenu == NULL) {
+ if (DEBUG)
+ fprintf(stderr,
+ "BPyMenus error: Couldn't create entry for: %s\n", fname);
+ parser_state = 0;
+ } else {
+ parser_state++;
+ }
+ }
+
+ } else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n",fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 6: /* optional elements */
+ /* Submenu: 'submenu name' related_1word_arg */
+ matches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail);
+ if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) {
+ bpymenu_AddSubEntry(scriptMenu, middle, tail);
+ } else {
+ /* Tooltip: 'tooltip for the menu */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) ||
+ (strstr(head, "Tip:") != NULL))) {
+ bpymenu_set_tooltip(scriptMenu, middle);
+ }
+ parser_state = 0;
+ }
+ break;
+
+ default:
+ parser_state = 0;
+ break;
+ }
+ }
+ }
+
+ else { /* shouldn't happen, it's checked in bpymenus_ParseDir */
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", fname);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* bpymenu_ParseDir:
+ * recursively scans folders looking for scripts to register.
+ *
+ * This function scans the scripts directory looking for .py files with the
+ * right header and menu info.
+ * - is_userdir defines if the script is in the default scripts dir or the
+ * user defined one (U.pythondir: is_userdir == 1);
+ * - parentdir is the parent dir name to store as part of the script filename,
+ * if we're down a subdir.
+ * Speed is important.
+ */
+static int bpymenu_ParseDir(char *dirname, char *parentdir, int is_userdir )
+{
+ DIR *dir;
+ FILE *file = NULL;
+ struct dirent *de;
+ struct stat status;
+ char *file_extension;
+ char path[FILE_MAX];
+ char subdir[FILE_MAX];
+ char *s = NULL;
+
+ dir = opendir(dirname);
+
+ if (dir != NULL) {
+ while ((de = readdir(dir)) != NULL) {
+
+ /* skip files and dirs starting with '.' or 'bpy' */
+ if ((de->d_name[0] == '.') || !strncmp(de->d_name, "bpy", 3)) {
+ continue;
+ }
+
+ BLI_make_file_string("/", path, dirname, de->d_name);
+
+ if (stat(path, &status) != 0) {
+ if (DEBUG)
+ fprintf(stderr, "stat %s failed: %s\n", path, strerror(errno));
+ }
+
+ if (S_ISREG(status.st_mode)) { /* is file */
+
+ file_extension = strstr(de->d_name, ".py");
+
+ if (file_extension && *(file_extension + 3) == '\0') {
+ file = fopen(path, "rb");
+
+ if (file) {
+ s = de->d_name;
+ if (parentdir) {
+ /* Join parentdir and de->d_name */
+ BLI_join_dirfile(subdir, parentdir, de->d_name);
+
+ s = subdir;
+ }
+ bpymenu_ParseFile(file, s, is_userdir);
+ fclose(file);
+ }
+
+ else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", path);
+ }
+ }
+ }
+
+ else if (S_ISDIR(status.st_mode)) { /* is subdir */
+ Dirs_Number++;
+ Dir_Depth++;
+ if (Dirs_Number > MAX_DIR_NUMBER) {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: too many subdirs.\n");
+ }
+ closedir(dir);
+ return -1;
+ }
+ else if (Dir_Depth > MAX_DIR_DEPTH) {
+ if (DEBUG)
+ fprintf(stderr,
+ "BPyMenus error: max depth reached traversing dir tree.\n");
+ closedir(dir);
+ return -1;
+ }
+ s = de->d_name;
+ if (parentdir) {
+ /* Join parentdir and de->d_name */
+ BLI_join_dirfile(subdir, parentdir, de->d_name);
+ s = subdir;
+ }
+ if (bpymenu_ParseDir(path, s, is_userdir) == -1) {
+ closedir(dir);
+ return -1;
+ }
+ Dir_Depth--;
+ }
+
+ }
+ closedir(dir);
+ }
+
+ else { /* open directory stream failed */
+ if (DEBUG)
+ fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )
+{
+ struct stat st;
+ int result;
+
+ result = stat( name, &st );
+
+ if( result == -1 )
+ return -1;
+
+ if( is_file ) {
+ if( !S_ISREG( st.st_mode ) )
+ return -2;
+ } else if( !S_ISDIR( st.st_mode ) )
+ return -2;
+
+ *mtime = st.st_mtime;
+
+ return 0;
+}
+
+/* BPyMenu_Init:
+ * import the bpython menus data to Blender, either from:
+ * - the BPYMENU_DATAFILE file (?/.blender/Bpymenus) or
+ * - the scripts dir(s), case newer than the datafile (then update the file).
+ * then fill the bpymenu table with this data.
+ * if param usedir != 0, then the data is recreated from the dir(s) anyway.
+*/
+int BPyMenu_Init( int usedir )
+{
+ char fname[FILE_MAXDIR];
+ char dirname[FILE_MAXDIR];
+ char upythondir[FILE_MAXDIR];
+ char *upydir = U.pythondir, *sdir = NULL;
+ time_t time_dir1 = 0, time_dir2 = 0, time_file = 0;
+ int stat_dir1 = 0, stat_dir2 = 0, stat_file = 0;
+ int i;
+
+ DEBUG = G.f & G_DEBUG; /* is Blender in debug mode (started with -d) ? */
+
+ /* init global bpymenu table (it is a list of pointers to struct BPyMenus
+ * for each available group: import, export, etc.) */
+ for( i = 0; i < PYMENU_TOTAL; i++ )
+ BPyMenuTable[i] = NULL;
+
+ if( DEBUG )
+ fprintf(stdout, "\nRegistering scripts in Blender menus ...\n\n" );
+
+ if( U.pythondir[0] == '\0') {
+ upydir = NULL;
+ }
+ else if (strcmp(U.pythondir, "/") == 0 || strcmp(U.pythondir, "//") == 0) {
+ /* these are not accepted to prevent possible slight slowdowns on startup;
+ * they should not be used as user defined scripts dir, anyway, also from
+ * speed considerations, since they'd not be dedicated scripts dirs */
+ if (DEBUG) fprintf(stderr,
+ "BPyMenus: invalid user defined Python scripts dir: \"/\" or \"//\".\n");
+ upydir = NULL;
+ }
+ else {
+ BLI_strncpy(upythondir, upydir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ }
+
+ sdir = bpy_gethome(1);
+
+ if (sdir) {
+ BLI_strncpy(dirname, sdir, FILE_MAXDIR);
+ stat_dir1 = bpymenu_GetStatMTime( dirname, 0, &time_dir1 );
+
+ if( stat_dir1 < 0 ) {
+ time_dir1 = 0;
+ if( DEBUG ) {
+ fprintf(stderr,
+ "\nDefault scripts dir: %s:\n%s\n", dirname, strerror(errno));
+ if( upydir )
+ fprintf(stdout,
+ "Getting scripts menu data from user defined dir: %s.\n",
+ upythondir );
+ }
+ }
+ }
+ else stat_dir1 = -1;
+
+ if( upydir ) {
+ stat_dir2 = bpymenu_GetStatMTime( upythondir, 0, &time_dir2 );
+
+ if( stat_dir2 < 0 ) {
+ time_dir2 = 0;
+ upydir = NULL;
+ if( DEBUG )
+ fprintf(stderr, "\nUser defined scripts dir: %s:\n%s.\n",
+ upythondir, strerror( errno ) );
+ if( stat_dir1 < 0 ) {
+ if( DEBUG )
+ fprintf(stderr, "\
+To have scripts in menus, please add them to the default scripts dir:\n\
+%s\n\
+and / or go to 'Info window -> File Paths tab' and set a valid path for\n\
+the user defined Python scripts dir.\n", dirname );
+ return -1;
+ }
+ }
+ }
+ else stat_dir2 = -1;
+
+ if( ( stat_dir1 < 0 ) && ( stat_dir2 < 0 ) ) {
+ if( DEBUG ) {
+ fprintf(stderr, "\nCannot register scripts in menus, no scripts dir"
+ " available.\nExpected default dir at: %s \n", dirname );
+ }
+ return -1;
+ }
+
+ if (usedir) stat_file = -1;
+ else { /* if we're not forced to use the dir */
+ char *homedir = bpy_gethome(0);
+
+ if (homedir) {
+ BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
+ stat_file = bpymenu_GetStatMTime( fname, 1, &time_file );
+ if( stat_file < 0 )
+ time_file = 0;
+
+ /* comparing dates */
+
+ if((stat_file == 0)
+ && (time_file > time_dir1) && (time_file > time_dir2))
+ { /* file is newer */
+ stat_file = bpymenu_CreateFromFile( ); /* -1 if an error occurred */
+ if( !stat_file && DEBUG )
+ fprintf(stdout,
+ "Getting menu data for scripts from file:\n%s\n\n", fname );
+ }
+ else stat_file = -1;
+ }
+ else stat_file = -1; /* -1 to use dirs: didn't use file or it was corrupted */
+ }
+
+ if( stat_file == -1 ) { /* use dirs */
+ if( DEBUG ) {
+ fprintf(stdout,
+ "Getting menu data for scripts from dir(s):\ndefault: %s\n", dirname );
+ if( upydir )
+ fprintf(stdout, "user defined: %s\n", upythondir );
+ fprintf(stdout, "\n");
+ }
+ if( stat_dir1 == 0 ) {
+ i = bpymenu_ParseDir( dirname, NULL, 0 );
+ if (i == -1 && DEBUG)
+ fprintf(stderr, "Default scripts dir does not seem valid.\n\n");
+ }
+ if( stat_dir2 == 0 ) {
+ BLI_strncpy(dirname, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(dirname, G.sce, 0);
+ i = bpymenu_ParseDir( dirname, NULL, 1 );
+ if (i == -1 && DEBUG)
+ fprintf(stderr, "User defined scripts dir does not seem valid.\n\n");
+ }
+
+ /* check if we got any data */
+ for( i = 0; i < PYMENU_TOTAL; i++ )
+ if( BPyMenuTable[i] )
+ break;
+
+ /* if we got, recreate the file */
+ if( i < PYMENU_TOTAL )
+ bpymenu_WriteDataFile( );
+ else if( DEBUG ) {
+ fprintf(stderr, "\n\
+Warning: Registering scripts in menus -- no info found.\n\
+Either your scripts dirs have no .py scripts or the scripts\n\
+don't have a header with registration data.\n\
+Default scripts dir is:\n\
+%s\n", dirname );
+ if( upydir )
+ fprintf(stderr, "User defined scripts dir is: %s\n",
+ upythondir );
+ }
+ }
+
+ return 0;
+}
diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h
new file mode 100644
index 00000000000..6cdea608b10
--- /dev/null
+++ b/source/blender/python/BPY_menus.h
@@ -0,0 +1,128 @@
+/*
+ * $Id: BPY_menus.h 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Matt Ebb
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef BPY_MENUS_H
+#define BPY_MENUS_H
+
+/* This header exposes BPyMenu related public declarations. The implementation
+ * adds 'dynamic' menus to Blender, letting scripts register themselves in any
+ * of a few pre-defined (trivial to upgrade) places in menus. These places or
+ * slots are called groups here (Import, Export, etc). This is how it works:
+ * - scripts at dirs user pref U.pythondir and .blender/scripts/ are scanned
+ * for registration info.
+ * - this data is also saved to a Bpymenus file at the user's .blender/ dir and
+ * only re-created when the scripts folder gets modified.
+ * - on start-up Blender uses this info to fill a table, which is used to
+ * create the menu entries when they are needed (see header_info.c or
+ * header_script.c, under source/blender/src/, for examples).
+*/
+
+/* These two structs hold py menu/submenu info.
+ * BPyMenu holds a script's name (as should appear in the menu) and filename,
+ * plus an optional list of submenus. Each submenu is related to a string
+ * (arg) that the script can get from the __script__ pydict, to know which
+ * submenu was chosen. */
+
+typedef struct BPySubMenu {
+ char *name;
+ char *arg;
+ struct BPySubMenu *next;
+} BPySubMenu;
+
+typedef struct BPyMenu {
+ char *name;
+ char *filename;
+ char *tooltip;
+ short version; /* Blender version */
+ int dir; /* 0: default, 1: U.pythondir */
+ struct BPySubMenu *submenus;
+ struct BPyMenu *next;
+} BPyMenu;
+
+/* Scripts can be added to only a few pre-defined places in menus, like
+ * File->Import, File->Export, etc. (for speed and better control).
+ * To make a new menu 'slot' available for scripts:
+ * - add an entry to the enum below, before PYMENU_TOTAL, of course;
+ * - update the bpymenu_group_atoi() and BPyMenu_group_itoa() functions in
+ * BPY_menus.c;
+ * - add the necessary code to the header_***.c file in
+ * source/blender/src/, like done in header_info.c for import/export;
+*/
+typedef enum {
+ PYMENU_ADD,/* creates new objects */
+ PYMENU_ANIMATION,
+ PYMENU_EXPORT,
+ PYMENU_IMPORT,
+ PYMENU_MATERIALS,
+ PYMENU_MESH,
+ PYMENU_MISC,
+ PYMENU_OBJECT,
+ PYMENU_RENDER,/* exporters to external renderers */
+ PYMENU_SYSTEM,
+ PYMENU_THEMES,
+ PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */
+ PYMENU_IMAGE,/* Image editing tools, to go in UV/Image editor space, 'Image' menu */
+ PYMENU_WIZARDS,/* complex 'app' scripts */
+
+ /* entries put after Wizards don't appear at the Scripts win->Scripts menu;
+ * see define right below */
+
+ PYMENU_FACESELECT,
+ PYMENU_WEIGHTPAINT,
+ PYMENU_VERTEXPAINT,
+ PYMENU_UVCALCULATION,
+ PYMENU_ARMATURE,
+ PYMENU_SCRIPTTEMPLATE,
+ PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/
+ PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */
+ PYMENU_HELPWEBSITES,/* Help -> Websites submenu */
+ PYMENU_MESHFACEKEY, /* face key in mesh editmode */
+ PYMENU_ADDMESH, /* adds mesh */
+ PYMENU_TOTAL
+} PYMENUHOOKS;
+
+#define PYMENU_SCRIPTS_MENU_TOTAL (PYMENU_WIZARDS + 1)
+
+/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
+ * where they can appear (see PYMENUHOOKS enum above).
+*/
+extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */
+
+/* public functions: */
+int BPyMenu_Init( int usedir );
+void BPyMenu_RemoveAllEntries( void );
+void BPyMenu_PrintAllEntries( void );
+char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short group );
+char *BPyMenu_group_itoa( short group );
+struct BPyMenu *BPyMenu_GetEntry( short group, short pos );
+
+#endif /* BPY_MENUS_H */
diff --git a/source/blender/python/Makefile b/source/blender/python/Makefile
index 8e2a04b8449..0c4b9ab6578 100644
--- a/source/blender/python/Makefile
+++ b/source/blender/python/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c
index de82781cf3a..f1a72270ea1 100644
--- a/source/blender/python/generic/BGL.c
+++ b/source/blender/python/generic/BGL.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BGL.c 20922 2009-06-16 07:16:51Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -83,13 +83,8 @@ static PyObject *Buffer_getattr( PyObject * self, char *name );
static PyObject *Buffer_repr( PyObject * self );
PyTypeObject buffer_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
+ PyObject_HEAD_INIT( NULL ) /* required python macro */
+ 0, /*ob_size */
"buffer", /*tp_name */
sizeof( Buffer ), /*tp_basicsize */
0, /*tp_itemsize */
@@ -1092,7 +1087,7 @@ static struct PyMethodDef BGL_methods[] = {
#if (PY_VERSION_HEX >= 0x03000000)
static struct PyModuleDef BGL_module_def = {
- PyModuleDef_HEAD_INIT,
+ {}, /* m_base */
"BGL", /* m_name */
0, /* m_doc */
0, /* m_size */
diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h
index 938c916bcea..e2d1b0bb495 100755
--- a/source/blender/python/generic/BGL.h
+++ b/source/blender/python/generic/BGL.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BGL.h 19717 2009-04-14 17:19:09Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c
index 8a748241570..d1e8b471f75 100644
--- a/source/blender/python/generic/Geometry.c
+++ b/source/blender/python/generic/Geometry.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Geometry.c 20922 2009-06-16 07:16:51Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -80,7 +80,7 @@ struct PyMethodDef M_Geometry_methods[] = {
#if (PY_VERSION_HEX >= 0x03000000)
static struct PyModuleDef M_Geometry_module_def = {
- PyModuleDef_HEAD_INIT,
+ {}, /* m_base */
"Geometry", /* m_name */
M_Geometry_doc, /* m_doc */
0, /* m_size */
@@ -164,10 +164,6 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
for( index = 0; index<len_polypoints; ++index, fp+=3) {
polyVec= PySequence_GetItem( polyLine, index );
if(VectorObject_Check(polyVec)) {
-
- if(!BaseMath_ReadCallback((VectorObject *)polyVec))
- ls_error= 1;
-
fp[0] = ((VectorObject *)polyVec)->vec[0];
fp[1] = ((VectorObject *)polyVec)->vec[1];
if( ((VectorObject *)polyVec)->size > 2 )
@@ -238,9 +234,6 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
return NULL;
}
- if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2))
- return NULL;
-
a1x= line_a1->vec[0];
a1y= line_a1->vec[1];
a2x= line_a2->vec[0];
@@ -337,10 +330,6 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2))
- return NULL;
-
/* accept 2d verts */
if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) }
@@ -374,9 +363,6 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args
return NULL;
}
- if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3))
- return NULL;
-
return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
}
@@ -395,9 +381,6 @@ static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
return NULL;
}
- if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4))
- return NULL;
-
return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
}
@@ -517,9 +500,6 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
return NULL;
}
- if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2))
- return NULL;
-
dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
diff --git a/source/blender/python/generic/Geometry.h b/source/blender/python/generic/Geometry.h
index ebfb054c54a..d7292e31fac 100644
--- a/source/blender/python/generic/Geometry.h
+++ b/source/blender/python/generic/Geometry.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Geometry.h 20007 2009-04-30 12:45:13Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Makefile b/source/blender/python/generic/Makefile
index 0dbfbd1d102..20cf7f19ec7 100644
--- a/source/blender/python/generic/Makefile
+++ b/source/blender/python/generic/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
index ffb110376b0..3c34a369baf 100644
--- a/source/blender/python/generic/Mathutils.c
+++ b/source/blender/python/generic/Mathutils.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Mathutils.c 20922 2009-06-16 07:16:51Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -96,7 +96,7 @@ struct PyMethodDef M_Mathutils_methods[] = {
#if (PY_VERSION_HEX >= 0x03000000)
static struct PyModuleDef M_Mathutils_module_def = {
- PyModuleDef_HEAD_INIT,
+ {}, /* m_base */
"Mathutils", /* m_name */
M_Mathutils_doc, /* m_doc */
0, /* m_size */
@@ -137,12 +137,81 @@ PyObject *Mathutils_Init(const char *from)
PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
- mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
-
return (submodule);
}
//-----------------------------METHODS----------------------------
+//----------------column_vector_multiplication (internal)---------
+//COLUMN VECTOR Multiplication (Matrix X Vector)
+// [1][2][3] [a]
+// [4][5][6] * [b]
+// [7][8][9] [c]
+//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
+{
+ float vecNew[4], vecCopy[4];
+ double dot = 0.0f;
+ int x, y, z = 0;
+
+ if(mat->rowSize != vec->size){
+ if(mat->rowSize == 4 && vec->size != 3){
+ PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
+ return NULL;
+ }else{
+ vecCopy[3] = 1.0f;
+ }
+ }
+
+ for(x = 0; x < vec->size; x++){
+ vecCopy[x] = vec->vec[x];
+ }
+
+ for(x = 0; x < mat->rowSize; x++) {
+ for(y = 0; y < mat->colSize; y++) {
+ dot += mat->matrix[x][y] * vecCopy[y];
+ }
+ vecNew[z++] = (float)dot;
+ dot = 0.0f;
+ }
+ return newVectorObject(vecNew, vec->size, Py_NEW);
+}
+
+//-----------------row_vector_multiplication (internal)-----------
+//ROW VECTOR Multiplication - Vector X Matrix
+//[x][y][z] * [1][2][3]
+// [4][5][6]
+// [7][8][9]
+//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
+{
+ float vecNew[4], vecCopy[4];
+ double dot = 0.0f;
+ int x, y, z = 0, vec_size = vec->size;
+
+ if(mat->colSize != vec_size){
+ if(mat->rowSize == 4 && vec_size != 3){
+ PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+ return NULL;
+ }else{
+ vecCopy[3] = 1.0f;
+ }
+ }
+
+ for(x = 0; x < vec_size; x++){
+ vecCopy[x] = vec->vec[x];
+ }
+
+ //muliplication
+ for(x = 0; x < mat->colSize; x++) {
+ for(y = 0; y < mat->rowSize; y++) {
+ dot += mat->matrix[y][x] * vecCopy[y];
+ }
+ vecNew[z++] = (float)dot;
+ dot = 0.0f;
+ }
+ return newVectorObject(vecNew, vec_size, Py_NEW);
+}
+
//-----------------quat_rotation (internal)-----------
//This function multiplies a vector/point * quat or vice versa
//to rotate the point/vector by the quaternion
@@ -155,15 +224,8 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
if(QuaternionObject_Check(arg1)){
quat = (QuaternionObject*)arg1;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
if(VectorObject_Check(arg2)){
vec = (VectorObject*)arg2;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
@@ -180,15 +242,8 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
}
}else if(VectorObject_Check(arg1)){
vec = (VectorObject*)arg1;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
if(QuaternionObject_Check(arg2)){
quat = (QuaternionObject*)arg2;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
@@ -253,9 +308,6 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
if(vec1->size != vec2->size)
goto AttributeError1; //bad sizes
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
//since size is the same....
size = vec1->size;
@@ -275,11 +327,8 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
angleRads = (double)saacos(dot);
-#ifdef USE_MATHUTILS_DEG
return PyFloat_FromDouble(angleRads * (180/ Py_PI));
-#else
- return PyFloat_FromDouble(angleRads);
-#endif
+
AttributeError1:
PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
return NULL;
@@ -304,9 +353,6 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
for(x = 0; x < vec1->size; x++) {
vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
@@ -331,10 +377,6 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
return NULL;
}
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
-
//since they are the same size...
size = vec1->size;
@@ -367,19 +409,12 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
return NULL;
}
-
-#ifdef USE_MATHUTILS_DEG
+
/* Clamp to -360:360 */
while (angle<-360.0f)
angle+=360.0;
while (angle>360.0f)
angle-=360.0;
-#else
- while (angle<-(Py_PI*2))
- angle+=(Py_PI*2);
- while (angle>(Py_PI*2))
- angle-=(Py_PI*2);
-#endif
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
@@ -404,16 +439,9 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
}
-#ifdef USE_MATHUTILS_DEG
//convert to radians
angle = angle * (float) (Py_PI / 180);
-#endif
-
if(axis == NULL && matSize == 2) {
//2D rotation matrix
mat[0] = (float) cos (angle);
@@ -510,10 +538,6 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v
PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
//create a identity matrix and add translation
Mat4One((float(*)[4]) mat);
mat[12] = vec->vec[0];
@@ -546,10 +570,6 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
}
if(vec == NULL) { //scaling along axis
if(matSize == 2) {
@@ -625,10 +645,6 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
}
if(vec == NULL) { //ortho projection onto cardinal plane
if(((strcmp(plane, "x") == 0)
@@ -785,10 +801,6 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
return NULL;
}
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
tempQuat[0] = quatU->quat[0];
tempQuat[1] = -quatU->quat[1];
tempQuat[2] = -quatU->quat[2];
@@ -816,10 +828,6 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
return NULL;
}
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
if(param > 1.0f || param < 0.0f) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
return NULL;
@@ -883,9 +891,6 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
return NULL;
}
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
- return NULL;
-
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
@@ -954,10 +959,6 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- return NULL;
-
if( vec1->size == 3 || vec1->size == 2) {
int result;
@@ -1028,10 +1029,6 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- return NULL;
-
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
@@ -1076,9 +1073,6 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
@@ -1111,9 +1105,6 @@ static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
if (vec1->size == 3) {
VECCOPY(v1, vec1->vec);
@@ -1163,8 +1154,8 @@ int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
}
/*---------------------- EXPP_VectorsAreEqual -------------------------
Builds on EXPP_FloatsAreEqual to test vectors */
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
-{
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
+
int x;
for (x=0; x< size; x++){
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
@@ -1174,86 +1165,6 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
}
-/* Mathutils Callbacks */
-
-/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
-Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-
-int Mathutils_RegisterCallback(Mathutils_Callback *cb)
-{
- int i;
-
- /* find the first free slot */
- for(i= 0; mathutils_callbacks[i]; i++) {
- if(mathutils_callbacks[i]==cb) /* alredy registered? */
- return i;
- }
-
- mathutils_callbacks[i] = cb;
- return i;
-}
-
-/* use macros to check for NULL */
-int _BaseMathObject_ReadCallback(BaseMathObject *self)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->get(self->cb_user, self->cb_subtype, self->data))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_WriteCallback(BaseMathObject *self)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->set(self->cb_user, self->cb_subtype, self->data))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->get_index(self->cb_user, self->cb_subtype, self->data, index))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->set_index(self->cb_user, self->cb_subtype, self->data, index))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-/* BaseMathObject generic functions for all mathutils types */
-PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type )
-{
- PyObject *ret= self->cb_user ? self->cb_user : Py_None;
- Py_INCREF(ret);
- return ret;
-}
-
-PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type )
-{
- return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
-}
-
-void BaseMathObject_dealloc(BaseMathObject * self)
-{
- /* only free non wrapped */
- if(self->wrapped != Py_WRAP)
- PyMem_Free(self->data);
-
- Py_XDECREF(self->cb_user);
- PyObject_DEL(self);
-}
+//#######################################################################
+//#############################DEPRECATED################################
diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h
index 6a4e28d6068..e8882c3dac2 100644
--- a/source/blender/python/generic/Mathutils.h
+++ b/source/blender/python/generic/Mathutils.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Mathutils.h 20332 2009-05-22 03:22:56Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -38,28 +38,10 @@
#include "quat.h"
#include "euler.h"
-/* #define USE_MATHUTILS_DEG - for backwards compat */
-
-/* Can cast different mathutils types to this, use for generic funcs */
-
-typedef struct {
- PyObject_VAR_HEAD
- float *data; /*array of data (alias), wrapped status depends on wrapped status */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
-} BaseMathObject;
-
-PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
-PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
-void BaseMathObject_dealloc(BaseMathObject * self);
-
-
-
-
PyObject *Mathutils_Init( const char * from );
+PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat);
+PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec);
PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
@@ -67,9 +49,8 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
#define Py_PI 3.14159265358979323846
-
-#define Py_NEW 1
-#define Py_WRAP 2
+#define Py_WRAP 1024
+#define Py_NEW 2048
/* Mathutils is used by the BGE and Blender so have to define
@@ -84,26 +65,4 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#endif
-typedef struct Mathutils_Callback Mathutils_Callback;
-struct Mathutils_Callback {
- int (*check)(PyObject *user); /* checks the user is still valid */
- int (*get)(PyObject *user, int subtype, float *from); /* gets the vector from the user */
- int (*set)(PyObject *user, int subtype, float *to); /* sets the users vector values once the vector is modified */
- int (*get_index)(PyObject *user, int subtype, float *from,int index); /* same as above but only for an index */
- int (*set_index)(PyObject *user, int subtype, float *to, int index); /* same as above but only for an index */
-};
-
-int Mathutils_RegisterCallback(Mathutils_Callback *cb);
-
-int _BaseMathObject_ReadCallback(BaseMathObject *self);
-int _BaseMathObject_WriteCallback(BaseMathObject *self);
-int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
-int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
-
-/* since this is called so often avoid where possible */
-#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1))
-#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1))
-#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1))
-#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1))
-
#endif /* EXPP_Mathutils_H */
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index c41ea386c0e..6789aea9c10 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: bpy_internal_import.c 20434 2009-05-26 18:06:09Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index aeeafb7c1c4..475ec8dd118 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: bpy_internal_import.h 20434 2009-05-26 18:06:09Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
index 769c82ed034..a65feb7e949 100644
--- a/source/blender/python/generic/euler.c
+++ b/source/blender/python/generic/euler.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: euler.c 20248 2009-05-18 04:11:54Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -65,12 +65,12 @@ static struct PyMethodDef Euler_methods[] = {
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
-static PyObject *Euler_new(PyObject * self, PyObject * args, PyObject * kwargs)
+static PyObject *Euler_new(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL;
int size, i;
- float eul[3];
+ float eul[3], scalar;
PyObject *e;
size = PyTuple_GET_SIZE(args);
@@ -102,13 +102,15 @@ static PyObject *Euler_new(PyObject * self, PyObject * args, PyObject * kwargs)
return NULL;
}
- eul[i]= (float)PyFloat_AsDouble(e);
+ scalar= (float)PyFloat_AsDouble(e);
Py_DECREF(e);
- if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
+ if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
+
+ eul[i]= scalar;
}
return newEulerObject(eul, Py_NEW);
}
@@ -121,18 +123,10 @@ static PyObject *Euler_ToQuat(EulerObject * self)
float eul[3], quat[4];
int x;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
EulToQuat(eul, quat);
-#else
- EulToQuat(self->eul, quat);
-#endif
-
return newQuaternionObject(quat, Py_NEW);
}
//----------------------------Euler.toMatrix()---------------------
@@ -143,17 +137,10 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
int x;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
EulToMat3(eul, (float (*)[3]) mat);
-#else
- EulToMat3(self->eul, (float (*)[3]) mat);
-#endif
return newMatrixObject(mat, 3, 3 , Py_NEW);
}
//----------------------------Euler.unique()-----------------------
@@ -165,20 +152,10 @@ static PyObject *Euler_Unique(EulerObject * self)
double piO2 = Py_PI / 2.0f;
double Opi2 = 1.0f / pi2;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
//radians
heading = self->eul[0] * (float)Py_PI / 180;
pitch = self->eul[1] * (float)Py_PI / 180;
bank = self->eul[2] * (float)Py_PI / 180;
-#else
- heading = self->eul[0];
- pitch = self->eul[1];
- bank = self->eul[2];
-#endif
-
//wrap heading in +180 / -180
pitch += Py_PI;
@@ -209,14 +186,11 @@ static PyObject *Euler_Unique(EulerObject * self)
heading -= (floor(heading * Opi2)) * pi2;
heading -= Py_PI;
-#ifdef USE_MATHUTILS_DEG
//back to degrees
self->eul[0] = (float)(heading * 180 / (float)Py_PI);
self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
self->eul[2] = (float)(bank * 180 / (float)Py_PI);
-#endif
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
@@ -228,7 +202,6 @@ static PyObject *Euler_Zero(EulerObject * self)
self->eul[1] = 0.0;
self->eul[2] = 0.0;
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
@@ -250,63 +223,42 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
return NULL;
}
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
//covert to radians
angle *= ((float)Py_PI / 180);
for(x = 0; x < 3; x++) {
self->eul[x] *= ((float)Py_PI / 180);
}
-#endif
euler_rot(self->eul, angle, *axis);
-
-#ifdef USE_MATHUTILS_DEG
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
-#endif
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
-#ifdef USE_MATHUTILS_DEG
float eul_from_rad[3];
int x;
-#endif
if(!EulerObject_Check(value)) {
PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
return NULL;
}
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
//covert to radians
for(x = 0; x < 3; x++) {
self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
}
compatible_eul(self->eul, eul_from_rad);
-#else
- compatible_eul(self->eul, value->eul);
-#endif
-
-#ifdef USE_MATHUTILS_DEG
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
-#endif
- BaseMath_WriteCallback(self);
+
Py_INCREF(self);
return (PyObject *)self;
}
@@ -315,21 +267,26 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
// return a copy of the euler
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
return newEulerObject(self->eul, Py_NEW);
}
+
+//----------------------------dealloc()(internal) ------------------
+//free the py_object
+static void Euler_dealloc(EulerObject * self)
+{
+ //only free py_data
+ if(self->data.py_data){
+ PyMem_Free(self->data.py_data);
+ }
+ PyObject_DEL(self);
+}
+
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Euler_repr(EulerObject * self)
{
char str[64];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
return PyUnicode_FromString(str);
}
@@ -340,18 +297,7 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
EulerObject *eulA = NULL, *eulB = NULL;
int result = 0;
- if(EulerObject_Check(objectA)) {
- eulA = (EulerObject*)objectA;
- if(!BaseMath_ReadCallback(eulA))
- return NULL;
- }
- if(EulerObject_Check(objectB)) {
- eulB = (EulerObject*)objectB;
- if(!BaseMath_ReadCallback(eulB))
- return NULL;
- }
-
- if (!eulA || !eulB){
+ if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
@@ -396,16 +342,13 @@ static int Euler_len(EulerObject * self)
//sequence accessor (get)
static PyObject *Euler_item(EulerObject * self, int i)
{
- if(i<0) i= 3-i;
+ if(i<0)
+ i= 3-i;
if(i < 0 || i >= 3) {
PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
return NULL;
}
-
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
return PyFloat_FromDouble(self->eul[i]);
}
@@ -420,7 +363,8 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
return -1;
}
- if(i<0) i= 3-i;
+ if(i<0)
+ i= 3-i;
if(i < 0 || i >= 3){
PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
@@ -428,10 +372,6 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
}
self->eul[i] = f;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
-
return 0;
}
//----------------------------object[z:y]------------------------
@@ -441,9 +381,6 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end)
PyObject *list = NULL;
int count;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
CLAMP(begin, 0, 3);
if (end<0) end= 4+end;
CLAMP(end, 0, 3);
@@ -464,10 +401,7 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
{
int i, y, size = 0;
float eul[3];
- PyObject *e;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
+ PyObject *e, *f;
CLAMP(begin, 0, 3);
if (end<0) end= 4+end;
@@ -487,20 +421,21 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
return -1;
}
- eul[i] = (float)PyFloat_AsDouble(e);
- Py_DECREF(e);
-
- if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
+ f = PyNumber_Float(e);
+ if(f == NULL) { // parsed item not a number
+ Py_DECREF(e);
PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
return -1;
}
+
+ eul[i] = (float)PyFloat_AS_DOUBLE(f);
+ Py_DECREF(f);
+ Py_DECREF(e);
}
//parsed well - now set in vector
for(y = 0; y < 3; y++){
self->eul[begin + y] = eul[y];
}
-
- BaseMath_WriteCallback(self);
return 0;
}
//-----------------PROTCOL DECLARATIONS--------------------------
@@ -515,30 +450,79 @@ static PySequenceMethods Euler_SeqMethods = {
};
+
/*
* vector axis, vector.x/y/z/w
*/
static PyObject *Euler_getAxis( EulerObject * self, void *type )
{
- return Euler_item(self, GET_INT_FROM_POINTER(type));
+ switch( (long)type ) {
+ case 'X': /* these are backwards, but that how it works */
+ return PyFloat_FromDouble(self->eul[0]);
+ case 'Y':
+ return PyFloat_FromDouble(self->eul[1]);
+ case 'Z':
+ return PyFloat_FromDouble(self->eul[2]);
+ }
+
+ PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis");
+ return NULL;
}
static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
{
- return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
+ float param= (float)PyFloat_AsDouble( value );
+
+ if (param==-1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis");
+ return -1;
+ }
+
+ switch( (long)type ) {
+ case 'X': /* these are backwards, but that how it works */
+ self->eul[0]= param;
+ break;
+ case 'Y':
+ self->eul[1]= param;
+ break;
+ case 'Z':
+ self->eul[2]= param;
+ break;
+ }
+
+ return 0;
+}
+
+static PyObject *Euler_getWrapped( VectorObject * self, void *type )
+{
+ if (self->wrapped == Py_WRAP)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
}
+
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
- {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
- {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
- {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
-
- {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
- {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
+ {"x",
+ (getter)Euler_getAxis, (setter)Euler_setAxis,
+ "Euler X axis",
+ (void *)'X'},
+ {"y",
+ (getter)Euler_getAxis, (setter)Euler_setAxis,
+ "Euler Y axis",
+ (void *)'Y'},
+ {"z",
+ (getter)Euler_getAxis, (setter)Euler_setAxis,
+ "Euler Z axis",
+ (void *)'Z'},
+ {"wrapped",
+ (getter)Euler_getWrapped, (setter)NULL,
+ "True when this wraps blenders internal data",
+ NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
@@ -554,7 +538,7 @@ PyTypeObject euler_Type = {
"euler", //tp_name
sizeof(EulerObject), //tp_basicsize
0, //tp_itemsize
- (destructor)BaseMathObject_dealloc, //tp_dealloc
+ (destructor)Euler_dealloc, //tp_dealloc
0, //tp_print
0, //tp_getattr
0, //tp_setattr
@@ -609,22 +593,24 @@ PyObject *newEulerObject(float *eul, int type)
int x;
self = PyObject_NEW(EulerObject, &euler_Type);
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
+ self->data.blend_data = NULL;
+ self->data.py_data = NULL;
if(type == Py_WRAP){
- self->eul = eul;
+ self->data.blend_data = eul;
+ self->eul = self->data.blend_data;
self->wrapped = Py_WRAP;
}else if (type == Py_NEW){
- self->eul = PyMem_Malloc(3 * sizeof(float));
+ self->data.py_data = PyMem_Malloc(3 * sizeof(float));
+ self->eul = self->data.py_data;
if(!eul) { //new empty
for(x = 0; x < 3; x++) {
self->eul[x] = 0.0f;
}
}else{
- VECCOPY(self->eul, eul);
+ for(x = 0; x < 3; x++){
+ self->eul[x] = eul[x];
+ }
}
self->wrapped = Py_NEW;
}else{ //bad type
@@ -632,16 +618,3 @@ PyObject *newEulerObject(float *eul, int type)
}
return (PyObject *)self;
}
-
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
-{
- EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h
index 0bff6de6964..3206668ffa0 100644
--- a/source/blender/python/generic/euler.h
+++ b/source/blender/python/generic/euler.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: euler.h 20248 2009-05-18 04:11:54Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -40,13 +40,12 @@ extern PyTypeObject euler_Type;
typedef struct {
PyObject_VAR_HEAD
- float *eul; /*1D array of data */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
+ struct{
+ float *py_data; //python managed
+ float *blend_data; //blender managed
+ }data;
+ float *eul; //1D array of data (alias)
+ int wrapped; //is wrapped data?
} EulerObject;
/*struct data contains a pointer to the actual data that the
@@ -56,6 +55,5 @@ blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newEulerObject( float *eul, int type );
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_euler_h */
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
index 311a14fbb0a..e2ab1c3c653 100644
--- a/source/blender/python/generic/matrix.c
+++ b/source/blender/python/generic/matrix.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: matrix.c 20249 2009-05-18 04:27:48Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -31,71 +31,6 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
-static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); /* utility func */
-
-
-/* matrix vector callbacks */
-int mathutils_matrix_vector_cb_index= -1;
-
-static int mathutils_matrix_vector_check(MatrixObject *self)
-{
- return BaseMath_ReadCallback(self);
-}
-
-static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- for(i=0; i<self->colSize; i++)
- vec_from[i]= self->matrix[subtype][i];
-
- return 1;
-}
-
-static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- for(i=0; i<self->colSize; i++)
- self->matrix[subtype][i]= vec_to[i];
-
- BaseMath_WriteCallback(self);
- return 1;
-}
-
-static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index)
-{
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- vec_from[index]= self->matrix[subtype][index];
- return 1;
-}
-
-static int mathutils_matrix_vector_set_index(MatrixObject *self, int subtype, float *vec_to, int index)
-{
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- self->matrix[subtype][index]= vec_to[index];
-
- BaseMath_WriteCallback(self);
- return 1;
-}
-
-Mathutils_Callback mathutils_matrix_vector_cb = {
- mathutils_matrix_vector_check,
- mathutils_matrix_vector_get,
- mathutils_matrix_vector_set,
- mathutils_matrix_vector_get_index,
- mathutils_matrix_vector_set_index
-};
-/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
-
/*-------------------------DOC STRINGS ---------------------------*/
static char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
static char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
@@ -164,8 +99,6 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
argObject = PyTuple_GET_ITEM(args, 0);
if(MatrixObject_Check(argObject)){
mat = (MatrixObject*)argObject;
- if(!BaseMath_ReadCallback(mat))
- return NULL;
argSize = mat->rowSize; //rows
seqSize = mat->colSize; //col
@@ -225,9 +158,6 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
{
float quat[4];
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
@@ -248,23 +178,13 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
EulerObject *eul_compat = NULL;
int x;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
return NULL;
if(eul_compat) {
- if(!BaseMath_ReadCallback(eul_compat))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
}
-#else
- VECCOPY(eul_compatf, eul_compat->eul);
-#endif
}
/*must be 3-4 cols, 3-4 rows, square matrix*/
@@ -282,12 +202,10 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
-#ifdef USE_MATHUTILS_DEG
/*have to convert to degrees*/
for(x = 0; x < 3; x++) {
eul[x] *= (float) (180 / Py_PI);
}
-#endif
return newEulerObject(eul, Py_NEW);
}
/*---------------------------Matrix.resize4x4() ------------------*/
@@ -295,20 +213,17 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
{
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
- if(self->wrapped==Py_WRAP){
- PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - make a copy and resize that");
- return NULL;
- }
- if(self->cb_user){
- PyErr_SetString(PyExc_TypeError, "cannot resize owned data - make a copy and resize that");
+ if(self->data.blend_data){
+ PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - only python matrices");
return NULL;
}
-
- self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16));
- if(self->contigPtr == NULL) {
+
+ self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16));
+ if(self->data.py_data == NULL) {
PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
return NULL;
}
+ self->contigPtr = self->data.py_data; /*force*/
self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4));
if(self->matrix == NULL) {
PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
@@ -351,10 +266,7 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
PyObject *Matrix_TranslationPart(MatrixObject * self)
{
float vec[4];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
+
if(self->colSize < 3 || self->rowSize < 4){
PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
return NULL;
@@ -372,9 +284,6 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(self->colSize < 3 || self->rowSize < 3){
PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
return NULL;
@@ -398,9 +307,6 @@ PyObject *Matrix_scalePart(MatrixObject * self)
float scale[3], rot[3];
float mat[3][3], imat[3][3], tmat[3][3];
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize == 4 && self->rowSize == 4)
Mat3CpyMat4(mat, (float (*)[4])*self->matrix);
@@ -431,9 +337,6 @@ PyObject *Matrix_Invert(MatrixObject * self)
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(self->rowSize != self->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported");
return NULL;
@@ -474,7 +377,6 @@ PyObject *Matrix_Invert(MatrixObject * self)
return NULL;
}
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
@@ -485,9 +387,6 @@ PyObject *Matrix_Determinant(MatrixObject * self)
{
float det = 0.0f;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(self->rowSize != self->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported");
return NULL;
@@ -513,9 +412,6 @@ PyObject *Matrix_Transpose(MatrixObject * self)
{
float t = 0.0f;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(self->rowSize != self->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported");
return NULL;
@@ -531,7 +427,6 @@ PyObject *Matrix_Transpose(MatrixObject * self)
Mat4Transp((float (*)[4])*self->matrix);
}
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
@@ -541,25 +436,18 @@ PyObject *Matrix_Transpose(MatrixObject * self)
PyObject *Matrix_Zero(MatrixObject * self)
{
int row, col;
-
+
for(row = 0; row < self->rowSize; row++) {
for(col = 0; col < self->colSize; col++) {
self->matrix[row][col] = 0.0f;
}
}
-
- if(!BaseMath_WriteCallback(self))
- return NULL;
-
Py_INCREF(self);
return (PyObject *)self;
}
/*---------------------------Matrix.identity(() ------------------*/
PyObject *Matrix_Identity(MatrixObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(self->rowSize != self->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n");
return NULL;
@@ -576,9 +464,6 @@ PyObject *Matrix_Identity(MatrixObject * self)
Mat4One((float (*)[4]) *self->matrix);
}
- if(!BaseMath_WriteCallback(self))
- return NULL;
-
Py_INCREF(self);
return (PyObject *)self;
}
@@ -586,12 +471,21 @@ PyObject *Matrix_Identity(MatrixObject * self)
/*---------------------------Matrix.inverted() ------------------*/
PyObject *Matrix_copy(MatrixObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW);
}
+/*----------------------------dealloc()(internal) ----------------*/
+/*free the py_object*/
+static void Matrix_dealloc(MatrixObject * self)
+{
+ PyMem_Free(self->matrix);
+ /*only free py_data*/
+ if(self->data.py_data){
+ PyMem_Free(self->data.py_data);
+ }
+ PyObject_DEL(self);
+}
+
/*----------------------------print object (internal)-------------*/
/*print the object to screen*/
static PyObject *Matrix_repr(MatrixObject * self)
@@ -599,9 +493,6 @@ static PyObject *Matrix_repr(MatrixObject * self)
int x, y;
char buffer[48], str[1024];
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
BLI_strncpy(str,"",1024);
for(x = 0; x < self->rowSize; x++){
sprintf(buffer, "[");
@@ -638,9 +529,6 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
matA = (MatrixObject*)objectA;
matB = (MatrixObject*)objectB;
- if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB))
- return NULL;
-
if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
@@ -688,14 +576,11 @@ static int Matrix_len(MatrixObject * self)
the wrapped vector gives direct access to the matrix data*/
static PyObject *Matrix_item(MatrixObject * self, int i)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(i < 0 || i >= self->rowSize) {
PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range");
return NULL;
}
- return newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, i);
+ return newVectorObject(self->matrix[i], self->colSize, Py_WRAP);
}
/*----------------------------object[]-------------------------
sequence accessor (set)*/
@@ -705,9 +590,6 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
float vec[4];
PyObject *m, *f;
- if(!BaseMath_ReadCallback(self))
- return -1;
-
if(i >= self->rowSize || i < 0){
PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n");
return -1;
@@ -741,8 +623,6 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
for(y = 0; y < size; y++){
self->matrix[i][y] = vec[y];
}
-
- BaseMath_WriteCallback(self);
return 0;
}else{
PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n");
@@ -756,9 +636,6 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
PyObject *list = NULL;
int count;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
CLAMP(begin, 0, self->rowSize);
CLAMP(end, 0, self->rowSize);
@@ -767,8 +644,7 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
list = PyList_New(end - begin);
for(count = begin; count < end; count++) {
PyList_SetItem(list, count - begin,
- newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, count));
-
+ newVectorObject(self->matrix[count], self->colSize, Py_WRAP));
}
return list;
@@ -783,9 +659,6 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
PyObject *subseq;
PyObject *m;
- if(!BaseMath_ReadCallback(self))
- return -1;
-
CLAMP(begin, 0, self->rowSize);
CLAMP(end, 0, self->rowSize);
begin = MIN2(begin,end);
@@ -843,8 +716,6 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
for(x = 0; x < (size * sub_size); x++){
self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
}
-
- BaseMath_WriteCallback(self);
return 0;
}else{
PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
@@ -867,10 +738,6 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
return NULL;
}
-
- if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
- return NULL;
-
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
return NULL;
@@ -900,10 +767,6 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
return NULL;
}
-
- if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
- return NULL;
-
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
return NULL;
@@ -928,16 +791,8 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
double dot = 0.0f;
MatrixObject *mat1 = NULL, *mat2 = NULL;
- if(MatrixObject_Check(m1)) {
- mat1 = (MatrixObject*)m1;
- if(!BaseMath_ReadCallback(mat1))
- return NULL;
- }
- if(MatrixObject_Check(m2)) {
- mat2 = (MatrixObject*)m2;
- if(!BaseMath_ReadCallback(mat2))
- return NULL;
- }
+ if(MatrixObject_Check(m1)) mat1 = (MatrixObject*)m1;
+ if(MatrixObject_Check(m2)) mat2 = (MatrixObject*)m2;
if(mat1 && mat2) { /*MATRIX * MATRIX*/
if(mat1->colSize != mat2->rowSize){
@@ -974,7 +829,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
else /* if(mat1) { */ {
if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
- return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */
+ return column_vector_multiplication(mat1, (VectorObject *)m2);
}
else {
scalar= PyFloat_AsDouble(m2);
@@ -996,9 +851,6 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
}
static PyObject* Matrix_inv(MatrixObject *self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
return Matrix_Invert(self);
}
@@ -1012,46 +864,6 @@ static PySequenceMethods Matrix_SeqMethods = {
(ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) Matrix_ass_slice, /* sq_ass_slice */
};
-
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Matrix_NumMethods = {
- (binaryfunc) Matrix_add, /*nb_add*/
- (binaryfunc) Matrix_sub, /*nb_subtract*/
- (binaryfunc) Matrix_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) 0, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) Matrix_inv, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
static PyNumberMethods Matrix_NumMethods = {
(binaryfunc) Matrix_add, /* __add__ */
(binaryfunc) Matrix_sub, /* __sub__ */
@@ -1077,7 +889,6 @@ static PyNumberMethods Matrix_NumMethods = {
(unaryfunc) 0, /* __oct__ */
(unaryfunc) 0, /* __hex__ */
};
-#endif
static PyObject *Matrix_getRowSize( MatrixObject * self, void *type )
{
@@ -1089,15 +900,21 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
return PyLong_FromLong((long) self->colSize);
}
+static PyObject *Matrix_getWrapped( MatrixObject * self, void *type )
+{
+ if (self->wrapped == Py_WRAP)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = {
{"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
{"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
- {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
- {"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "",
- NULL},
+ {"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
@@ -1113,7 +930,7 @@ PyTypeObject matrix_Type = {
"matrix", /*tp_name*/
sizeof(MatrixObject), /*tp_basicsize*/
0, /*tp_itemsize*/
- (destructor)BaseMathObject_dealloc, /*tp_dealloc*/
+ (destructor)Matrix_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -1167,7 +984,7 @@ self->matrix self->contiguous_ptr (reference to data.xxx)
[4]
[5]
....
-self->matrix[1][1] = self->contigPtr[4] */
+self->matrix[1][1] = self->contiguous_ptr[4] = self->data.xxx_data[4]*/
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
@@ -1185,15 +1002,14 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
}
self = PyObject_NEW(MatrixObject, &matrix_Type);
+ self->data.blend_data = NULL;
+ self->data.py_data = NULL;
self->rowSize = rowSize;
self->colSize = colSize;
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
- self->contigPtr = mat;
+ self->data.blend_data = mat;
+ self->contigPtr = self->data.blend_data;
/*create pointer array*/
self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
if(self->matrix == NULL) { /*allocation failure*/
@@ -1206,15 +1022,16 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
}
self->wrapped = Py_WRAP;
}else if (type == Py_NEW){
- self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float));
- if(self->contigPtr == NULL) { /*allocation failure*/
+ self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float));
+ if(self->data.py_data == NULL) { /*allocation failure*/
PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n");
return NULL;
}
+ self->contigPtr = self->data.py_data;
/*create pointer array*/
self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
if(self->matrix == NULL) { /*allocation failure*/
- PyMem_Free(self->contigPtr);
+ PyMem_Free(self->data.py_data);
PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
return NULL;
}
@@ -1239,53 +1056,3 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
}
return (PyObject *) self;
}
-
-PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
-{
- MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
- return (PyObject *) self;
-}
-
-//----------------column_vector_multiplication (internal)---------
-//COLUMN VECTOR Multiplication (Matrix X Vector)
-// [1][2][3] [a]
-// [4][5][6] * [b]
-// [7][8][9] [c]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
-{
- float vecNew[4], vecCopy[4];
- double dot = 0.0f;
- int x, y, z = 0;
-
- if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec))
- return NULL;
-
- if(mat->rowSize != vec->size){
- if(mat->rowSize == 4 && vec->size != 3){
- PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
- return NULL;
- }else{
- vecCopy[3] = 1.0f;
- }
- }
-
- for(x = 0; x < vec->size; x++){
- vecCopy[x] = vec->vec[x];
- }
-
- for(x = 0; x < mat->rowSize; x++) {
- for(y = 0; y < mat->colSize; y++) {
- dot += mat->matrix[x][y] * vecCopy[y];
- }
- vecNew[z++] = (float)dot;
- dot = 0.0f;
- }
- return newVectorObject(vecNew, vec->size, Py_NEW);
-}
diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h
index 4b073668969..ef82263fe00 100644
--- a/source/blender/python/generic/matrix.h
+++ b/source/blender/python/generic/matrix.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: matrix.h 20248 2009-05-18 04:11:54Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -37,19 +37,17 @@ extern PyTypeObject matrix_Type;
#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type)
typedef float **ptRow;
-typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */
- PyObject_VAR_HEAD
- float *contigPtr; /*1D array of data (alias)*/
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /*is wrapped data?*/
- /* end BaseMathObject */
-
- unsigned char rowSize;
- unsigned int colSize;
- ptRow matrix; /*ptr to the contigPtr (accessor)*/
-
+typedef struct _Matrix {
+ PyObject_VAR_HEAD
+ struct{
+ float *py_data; /*python managed*/
+ float *blend_data; /*blender managed*/
+ }data;
+ ptRow matrix; /*ptr to the contigPtr (accessor)*/
+ float *contigPtr; /*1D array of data (alias)*/
+ int rowSize;
+ int colSize;
+ int wrapped; /*is wrapped data?*/
} MatrixObject;
/*struct data contains a pointer to the actual data that the
@@ -59,9 +57,5 @@ blender (stored in blend_data). This is an either/or struct not both*/
/*prototypes*/
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type);
-PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype);
-
-extern int mathutils_matrix_vector_cb_index;
-extern struct Mathutils_Callback mathutils_matrix_vector_cb;
#endif /* EXPP_matrix_H */
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
index 7cd3cf738dd..4ad5d07b3b8 100644
--- a/source/blender/python/generic/quat.c
+++ b/source/blender/python/generic/quat.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: quat.c 20332 2009-05-22 03:22:56Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -75,10 +75,10 @@ static struct PyMethodDef Quaternion_methods[] = {
//----------------------------------Mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *listObject = NULL, *n, *q;
+ PyObject *listObject = NULL, *n, *q, *f;
int size, i;
- float quat[4];
- double angle = 0.0f;
+ float quat[4], scalar;
+ double norm = 0.0f, angle = 0.0f;
size = PyTuple_GET_SIZE(args);
if (size == 1 || size == 2) { //seq?
@@ -151,21 +151,29 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
return NULL;
}
- quat[i] = PyFloat_AsDouble(q);
- Py_DECREF(q);
-
- if (quat[i]==-1 && PyErr_Occurred()) {
+ scalar = PyFloat_AsDouble(q);
+ if (scalar==-1 && PyErr_Occurred()) {
+ Py_DECREF(q);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
- }
- if(size == 3) //calculate the quat based on axis/angle
-#ifdef USE_MATHUTILS_DEG
- AxisAngleToQuat(quat, quat, angle * (Py_PI / 180));
-#else
- AxisAngleToQuat(quat, quat, angle);
-#endif
+ quat[i] = scalar;
+ Py_DECREF(f);
+ Py_DECREF(q);
+ }
+ if(size == 3){ //calculate the quat based on axis/angle
+ norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
+ quat[0] /= (float)norm;
+ quat[1] /= (float)norm;
+ quat[2] /= (float)norm;
+
+ angle = angle * (Py_PI / 180);
+ quat[3] =(float) (sin(angle/ 2.0f)) * quat[2];
+ quat[2] =(float) (sin(angle/ 2.0f)) * quat[1];
+ quat[1] =(float) (sin(angle/ 2.0f)) * quat[0];
+ quat[0] =(float) (cos(angle/ 2.0f));
+ }
return newQuaternionObject(quat, Py_NEW);
}
@@ -182,47 +190,33 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
return NULL;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
if(eul_compat) {
float mat[3][3], eul_compatf[3];
- if(!BaseMath_ReadCallback(eul_compat))
- return NULL;
-
- QuatToMat3(self->quat, mat);
-
-#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
}
+
+ QuatToMat3(self->quat, mat);
Mat3ToCompatibleEul(mat, eul, eul_compatf);
-#else
- Mat3ToCompatibleEul(mat, eul, eul_compat->eul);
-#endif
}
else {
QuatToEul(self->quat, eul);
}
-#ifdef USE_MATHUTILS_DEG
+
for(x = 0; x < 3; x++) {
eul[x] *= (180 / (float)Py_PI);
}
-#endif
return newEulerObject(eul, Py_NEW);
}
//----------------------------Quaternion.toMatrix()------------------
//return the quat as a matrix
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
{
- float mat[9]; /* all values are set */
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
+ float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
QuatToMat3(self->quat, (float (*)[3]) mat);
+
return newMatrixObject(mat, 3, 3, Py_NEW);
}
@@ -237,9 +231,6 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
return NULL;
}
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
QuatMul(quat, self->quat, value->quat);
return newQuaternionObject(quat, Py_NEW);
}
@@ -248,27 +239,25 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
//return the dot quat
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{
+ int x;
+ double dot = 0.0;
+
if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- return PyFloat_FromDouble(QuatDot(self->quat, value->quat));
+
+ for(x = 0; x < 4; x++) {
+ dot += self->quat[x] * value->quat[x];
+ }
+ return PyFloat_FromDouble(dot);
}
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
static PyObject *Quaternion_Normalize(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
NormalQuat(self->quat);
-
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -276,12 +265,20 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
//invert the quat
static PyObject *Quaternion_Inverse(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
+ double mag = 0.0f;
+ int x;
- QuatInv(self->quat);
+ for(x = 1; x < 4; x++) {
+ self->quat[x] = -self->quat[x];
+ }
+ for(x = 0; x < 4; x++) {
+ mag += (self->quat[x] * self->quat[x]);
+ }
+ mag = sqrt(mag);
+ for(x = 0; x < 4; x++) {
+ self->quat[x] /= (float)(mag * mag);
+ }
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -289,12 +286,11 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
//generate the identity quaternion
static PyObject *Quaternion_Identity(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatOne(self->quat);
+ self->quat[0] = 1.0;
+ self->quat[1] = 0.0;
+ self->quat[2] = 0.0;
+ self->quat[3] = 0.0;
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -302,12 +298,10 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
//negate the quat
static PyObject *Quaternion_Negate(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatMulf(self->quat, -1.0f);
-
- BaseMath_WriteCallback(self);
+ int x;
+ for(x = 0; x < 4; x++) {
+ self->quat[x] = -self->quat[x];
+ }
Py_INCREF(self);
return (PyObject*)self;
}
@@ -315,12 +309,10 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
//negate the vector part
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatConj(self->quat);
-
- BaseMath_WriteCallback(self);
+ int x;
+ for(x = 1; x < 4; x++) {
+ self->quat[x] = -self->quat[x];
+ }
Py_INCREF(self);
return (PyObject*)self;
}
@@ -328,21 +320,25 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
//return a copy of the quat
static PyObject *Quaternion_copy(QuaternionObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
return newQuaternionObject(self->quat, Py_NEW);
}
+//----------------------------dealloc()(internal) ------------------
+//free the py_object
+static void Quaternion_dealloc(QuaternionObject * self)
+{
+ //only free py_data
+ if(self->data.py_data){
+ PyMem_Free(self->data.py_data);
+ }
+ PyObject_DEL(self);
+}
+
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Quaternion_repr(QuaternionObject * self)
{
char str[64];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
return PyUnicode_FromString(str);
}
@@ -353,24 +349,15 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
QuaternionObject *quatA = NULL, *quatB = NULL;
int result = 0;
- if(QuaternionObject_Check(objectA)) {
- quatA = (QuaternionObject*)objectA;
- if(!BaseMath_ReadCallback(quatA))
- return NULL;
- }
- if(QuaternionObject_Check(objectB)) {
- quatB = (QuaternionObject*)objectB;
- if(!BaseMath_ReadCallback(quatB))
- return NULL;
- }
-
- if (!quatA || !quatB){
+ if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
+ quatA = (QuaternionObject*)objectA;
+ quatB = (QuaternionObject*)objectB;
switch (comparison_type){
case Py_EQ:
@@ -407,16 +394,10 @@ static int Quaternion_len(QuaternionObject * self)
//sequence accessor (get)
static PyObject *Quaternion_item(QuaternionObject * self, int i)
{
- if(i<0) i= 4-i;
-
if(i < 0 || i >= 4) {
PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
return NULL;
}
-
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
return PyFloat_FromDouble(self->quat[i]);
}
@@ -424,23 +405,21 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i)
//sequence accessor (set)
static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
{
- float scalar= (float)PyFloat_AsDouble(ob);
- if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
+ PyObject *f = NULL;
+
+ f = PyNumber_Float(ob);
+ if(f == NULL) { // parsed item not a number
+ PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n");
return -1;
}
- if(i<0) i= 4-i;
-
if(i < 0 || i >= 4){
+ Py_DECREF(f);
PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
return -1;
}
- self->quat[i] = scalar;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
-
+ self->quat[i] = (float)PyFloat_AS_DOUBLE(f);
+ Py_DECREF(f);
return 0;
}
//----------------------------object[z:y]------------------------
@@ -450,9 +429,6 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
PyObject *list = NULL;
int count;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
CLAMP(begin, 0, 4);
if (end<0) end= 5+end;
CLAMP(end, 0, 4);
@@ -468,14 +444,12 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
-static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
+static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
+ PyObject * seq)
{
int i, y, size = 0;
float quat[4];
- PyObject *q;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
+ PyObject *q, *f;
CLAMP(begin, 0, 4);
if (end<0) end= 5+end;
@@ -495,19 +469,21 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyO
return -1;
}
- quat[i]= (float)PyFloat_AsDouble(q);
- Py_DECREF(q);
-
- if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ f = PyNumber_Float(q);
+ if(f == NULL) { // parsed item not a number
+ Py_DECREF(q);
PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
return -1;
}
+
+ quat[i] = (float)PyFloat_AS_DOUBLE(f);
+ Py_DECREF(f);
+ Py_DECREF(q);
}
//parsed well - now set in vector
- for(y = 0; y < size; y++)
+ for(y = 0; y < size; y++){
self->quat[begin + y] = quat[y];
-
- BaseMath_WriteCallback(self);
+ }
return 0;
}
//------------------------NUMERIC PROTOCOLS----------------------
@@ -515,6 +491,7 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyO
//addition
static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
{
+ int x;
float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
@@ -522,13 +499,14 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL;
}
+
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
- if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
- return NULL;
+ for(x = 0; x < 4; x++) {
+ quat[x] = quat1->quat[x] + quat2->quat[x];
+ }
- QuatAdd(quat, quat1->quat, quat2->quat, 1.0f);
return newQuaternionObject(quat, Py_NEW);
}
//------------------------obj - obj------------------------------
@@ -547,9 +525,6 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
- if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
- return NULL;
-
for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] - quat2->quat[x];
}
@@ -560,31 +535,29 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
//mulplication
static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
{
+ int x;
float quat[4], scalar;
+ double dot = 0.0f;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
VectorObject *vec = NULL;
- if(QuaternionObject_Check(q1)) {
- quat1 = (QuaternionObject*)q1;
- if(!BaseMath_ReadCallback(quat1))
- return NULL;
- }
- if(QuaternionObject_Check(q2)) {
- quat2 = (QuaternionObject*)q2;
- if(!BaseMath_ReadCallback(quat2))
- return NULL;
- }
+ quat1 = (QuaternionObject*)q1;
+ quat2 = (QuaternionObject*)q2;
- if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
- return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat));
+ if(QuaternionObject_Check(q1) && QuaternionObject_Check(q2)) { /* QUAT*QUAT (dot product) */
+ for(x = 0; x < 4; x++) {
+ dot += quat1->quat[x] * quat1->quat[x];
+ }
+ return PyFloat_FromDouble(dot);
}
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
if(!QuaternionObject_Check(q1)) {
scalar= PyFloat_AsDouble(q1);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
- QUATCOPY(quat, quat2->quat);
- QuatMulf(quat, scalar);
+ for(x = 0; x < 4; x++) {
+ quat[x] = quat2->quat[x] * scalar;
+ }
return newQuaternionObject(quat, Py_NEW);
}
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
@@ -597,13 +570,14 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
return NULL;
}
- return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
+ return quat_rotation((PyObject*)quat1, (PyObject*)vec);
}
scalar= PyFloat_AsDouble(q2);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
- QUATCOPY(quat, quat1->quat);
- QuatMulf(quat, scalar);
+ for(x = 0; x < 4; x++) {
+ quat[x] = quat1->quat[x] * scalar;
+ }
return newQuaternionObject(quat, Py_NEW);
}
}
@@ -622,45 +596,6 @@ static PySequenceMethods Quaternion_SeqMethods = {
(ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */
};
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Quaternion_NumMethods = {
- (binaryfunc) Quaternion_add, /*nb_add*/
- (binaryfunc) Quaternion_sub, /*nb_subtract*/
- (binaryfunc) Quaternion_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) 0, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) 0, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
static PyNumberMethods Quaternion_NumMethods = {
(binaryfunc) Quaternion_add, /* __add__ */
(binaryfunc) Quaternion_sub, /* __sub__ */
@@ -685,31 +620,76 @@ static PyNumberMethods Quaternion_NumMethods = {
(unaryfunc) 0, /* __float__ */
(unaryfunc) 0, /* __oct__ */
(unaryfunc) 0, /* __hex__ */
+
};
-#endif
+
static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
{
- return Quaternion_item(self, GET_INT_FROM_POINTER(type));
+ switch( (long)type ) {
+ case 'W':
+ return PyFloat_FromDouble(self->quat[0]);
+ case 'X':
+ return PyFloat_FromDouble(self->quat[1]);
+ case 'Y':
+ return PyFloat_FromDouble(self->quat[2]);
+ case 'Z':
+ return PyFloat_FromDouble(self->quat[3]);
+ }
+
+ PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis");
+ return NULL;
}
static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
{
- return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
+ float param= (float)PyFloat_AsDouble( value );
+
+ if (param==-1 && PyErr_Occurred()) {
+ PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+ return -1;
+ }
+ switch( (long)type ) {
+ case 'W':
+ self->quat[0]= param;
+ break;
+ case 'X':
+ self->quat[1]= param;
+ break;
+ case 'Y':
+ self->quat[2]= param;
+ break;
+ case 'Z':
+ self->quat[3]= param;
+ break;
+ }
+
+ return 0;
+}
+
+static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type )
+{
+ if (self->wrapped == Py_WRAP)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
}
static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
{
- return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat)));
+ double mag = 0.0;
+ int i;
+ for(i = 0; i < 4; i++) {
+ mag += self->quat[i] * self->quat[i];
+ }
+ return PyFloat_FromDouble(sqrt(mag));
}
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
{
double ang = self->quat[0];
ang = 2 * (saacos(ang));
-#ifdef USE_MATHUTILS_DEG
ang *= (180 / Py_PI);
-#endif
return PyFloat_FromDouble(ang);
}
@@ -741,19 +721,19 @@ static PyGetSetDef Quaternion_getseters[] = {
{"w",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion W value",
- (void *)0},
+ (void *)'W'},
{"x",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion X axis",
- (void *)1},
+ (void *)'X'},
{"y",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Y axis",
- (void *)2},
+ (void *)'Y'},
{"z",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Z axis",
- (void *)3},
+ (void *)'Z'},
{"magnitude",
(getter)Quaternion_getMagnitude, (setter)NULL,
"Size of the quaternion",
@@ -767,14 +747,9 @@ static PyGetSetDef Quaternion_getseters[] = {
"quaternion axis as a vector",
NULL},
{"wrapped",
- (getter)BaseMathObject_getWrapped, (setter)NULL,
+ (getter)Quaternion_getWrapped, (setter)NULL,
"True when this wraps blenders internal data",
NULL},
- {"__owner__",
- (getter)BaseMathObject_getOwner, (setter)NULL,
- "Read only owner for vectors that depend on another object",
- NULL},
-
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
@@ -791,7 +766,7 @@ PyTypeObject quaternion_Type = {
"quaternion", //tp_name
sizeof(QuaternionObject), //tp_basicsize
0, //tp_itemsize
- (destructor)BaseMathObject_dealloc, //tp_dealloc
+ (destructor)Quaternion_dealloc, //tp_dealloc
0, //tp_print
0, //tp_getattr
0, //tp_setattr
@@ -843,22 +818,26 @@ PyTypeObject quaternion_Type = {
PyObject *newQuaternionObject(float *quat, int type)
{
QuaternionObject *self;
+ int x;
self = PyObject_NEW(QuaternionObject, &quaternion_Type);
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
+ self->data.blend_data = NULL;
+ self->data.py_data = NULL;
if(type == Py_WRAP){
- self->quat = quat;
+ self->data.blend_data = quat;
+ self->quat = self->data.blend_data;
self->wrapped = Py_WRAP;
}else if (type == Py_NEW){
- self->quat = PyMem_Malloc(4 * sizeof(float));
+ self->data.py_data = PyMem_Malloc(4 * sizeof(float));
+ self->quat = self->data.py_data;
if(!quat) { //new empty
- QuatOne(self->quat);
+ Quaternion_Identity(self);
+ Py_DECREF(self);
}else{
- QUATCOPY(self->quat, quat);
+ for(x = 0; x < 4; x++){
+ self->quat[x] = quat[x];
+ }
}
self->wrapped = Py_NEW;
}else{ //bad type
@@ -866,16 +845,3 @@ PyObject *newQuaternionObject(float *quat, int type)
}
return (PyObject *) self;
}
-
-PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
-{
- QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h
index 2e74b5fa7f9..cfb50e4dbe1 100644
--- a/source/blender/python/generic/quat.h
+++ b/source/blender/python/generic/quat.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: quat.h 20332 2009-05-22 03:22:56Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -38,15 +38,14 @@ extern PyTypeObject quaternion_Type;
#define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type)
-typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
+typedef struct {
PyObject_VAR_HEAD
- float *quat; /* 1D array of data (alias) */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
+ struct{
+ float *py_data; //python managed
+ float *blend_data; //blender managed
+ }data;
+ float *quat; //1D array of data (alias)
+ int wrapped; //is wrapped data?
} QuaternionObject;
/*struct data contains a pointer to the actual data that the
@@ -56,6 +55,5 @@ blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newQuaternionObject( float *quat, int type );
-PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_quat_h */
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index d8d4c33b6f8..562413c6967 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: vector.c 20332 2009-05-22 03:22:56Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -39,8 +39,6 @@
#define SWIZZLE_VALID_AXIS 0x4
#define SWIZZLE_AXIS 0x3
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
-
/*-------------------------DOC STRINGS ---------------------------*/
static char Vector_Zero_doc[] = "() - set all values in the vector to 0";
static char Vector_Normalize_doc[] = "() - normalize the vector";
@@ -62,7 +60,7 @@ static PyObject *Vector_Resize2D( VectorObject * self );
static PyObject *Vector_Resize3D( VectorObject * self );
static PyObject *Vector_Resize4D( VectorObject * self );
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
-static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value );
+static PyObject *Vector_Reflect( VectorObject * self, PyObject * value );
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
static PyObject *Vector_copy( VectorObject * self );
@@ -72,8 +70,8 @@ static struct PyMethodDef Vector_methods[] = {
{"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
{"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
{"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
- {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc},
- {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc},
+ {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc},
+ {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc},
{"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
{"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc},
{"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Dot_doc},
@@ -143,8 +141,6 @@ static PyObject *Vector_Zero(VectorObject * self)
for(i = 0; i < self->size; i++) {
self->vec[i] = 0.0f;
}
-
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -155,9 +151,6 @@ static PyObject *Vector_Normalize(VectorObject * self)
int i;
float norm = 0.0f;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
for(i = 0; i < self->size; i++) {
norm += self->vec[i] * self->vec[i];
}
@@ -165,8 +158,6 @@ static PyObject *Vector_Normalize(VectorObject * self)
for(i = 0; i < self->size; i++) {
self->vec[i] /= norm;
}
-
- BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -180,11 +171,6 @@ static PyObject *Vector_Resize2D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
@@ -203,11 +189,6 @@ static PyObject *Vector_Resize3D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
@@ -229,11 +210,6 @@ static PyObject *Vector_Resize4D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
return NULL;
}
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
@@ -265,9 +241,6 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" );
return NULL;
}
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
if (strack) {
if (strlen(strack) == 2) {
@@ -369,8 +342,9 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
return a reflected vector on the mirror normal
((2 * DotVecs(vec, mirror)) * mirror) - vec
using arithb.c would be nice here */
-static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
+static PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
{
+ VectorObject *mirrvec;
float mirror[3];
float vec[3];
float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -384,13 +358,11 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" );
return NULL;
}
+ mirrvec = (VectorObject *)value;
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- mirror[0] = value->vec[0];
- mirror[1] = value->vec[1];
- if (value->size > 2) mirror[2] = value->vec[2];
+ mirror[0] = mirrvec->vec[0];
+ mirror[1] = mirrvec->vec[1];
+ if (mirrvec->size > 2) mirror[2] = mirrvec->vec[2];
else mirror[2] = 0.0;
/* normalize, whos idea was it not to use arithb.c? :-/ */
@@ -431,9 +403,6 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
return NULL;
}
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW);
Crossf(vecCross->vec, self->vec, value->vec);
return (PyObject *)vecCross;
@@ -454,9 +423,6 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return NULL;
}
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
for(x = 0; x < self->size; x++) {
dot += self->vec[x] * value->vec[x];
}
@@ -467,12 +433,20 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return a copy of the vector */
static PyObject *Vector_copy(VectorObject * self)
{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
return newVectorObject(self->vec, self->size, Py_NEW);
}
+/*----------------------------dealloc()(internal) ----------------
+ free the py_object */
+static void Vector_dealloc(VectorObject * self)
+{
+ /* only free non wrapped */
+ if(self->wrapped != Py_WRAP){
+ PyMem_Free(self->vec);
+ }
+ PyObject_DEL(self);
+}
+
/*----------------------------print object (internal)-------------
print the object to screen */
static PyObject *Vector_repr(VectorObject * self)
@@ -480,9 +454,6 @@ static PyObject *Vector_repr(VectorObject * self)
int i;
char buffer[48], str[1024];
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
BLI_strncpy(str,"[",1024);
for(i = 0; i < self->size; i++){
if(i < (self->size - 1)){
@@ -508,16 +479,11 @@ static int Vector_len(VectorObject * self)
sequence accessor (get)*/
static PyObject *Vector_item(VectorObject * self, int i)
{
- if(i<0) i= self->size-i;
-
if(i < 0 || i >= self->size) {
PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n");
return NULL;
}
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
return PyFloat_FromDouble(self->vec[i]);
}
@@ -531,16 +497,11 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
return -1;
}
- if(i<0) i= self->size-i;
-
if(i < 0 || i >= self->size){
PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n");
return -1;
}
self->vec[i] = scalar;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
return 0;
}
@@ -551,9 +512,6 @@ static PyObject *Vector_slice(VectorObject * self, int begin, int end)
PyObject *list = NULL;
int count;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
CLAMP(begin, 0, self->size);
if (end<0) end= self->size+end+1;
CLAMP(end, 0, self->size);
@@ -576,9 +534,6 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
float vec[4], scalar;
PyObject *v;
- if(!BaseMath_ReadCallback(self))
- return -1;
-
CLAMP(begin, 0, self->size);
if (end<0) end= self->size+end+1;
CLAMP(end, 0, self->size);
@@ -611,10 +566,6 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
for(y = 0; y < size; y++){
self->vec[begin + y] = vec[y];
}
-
- if(!BaseMath_WriteCallback(self))
- return -1;
-
return 0;
}
/*------------------------NUMERIC PROTOCOLS----------------------
@@ -635,10 +586,6 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
/*VECTOR + VECTOR*/
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
@@ -670,10 +617,6 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
/*VECTOR + VECTOR*/
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
@@ -686,7 +629,6 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
return v1;
}
- BaseMath_WriteCallback(vec1);
PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
return NULL;
}
@@ -706,9 +648,6 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
return NULL;
@@ -724,7 +663,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
subtraction*/
static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
{
- int i;
+ int i, size;
VectorObject *vec1 = NULL, *vec2 = NULL;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
@@ -738,15 +677,12 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
return NULL;
}
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
+ size = vec1->size;
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] = vec1->vec[i] - vec2->vec[i];
}
- BaseMath_WriteCallback(vec1);
Py_INCREF( v1 );
return v1;
}
@@ -758,17 +694,11 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if VectorObject_Check(v1) {
+ if VectorObject_Check(v1)
vec1= (VectorObject *)v1;
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
- }
- if VectorObject_Check(v2) {
- vec2= (VectorObject *)v2;
- if(!BaseMath_ReadCallback(vec2))
- return NULL;
- }
+ if VectorObject_Check(v2)
+ vec2= (VectorObject *)v2;
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
@@ -797,8 +727,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
/* VEC * MATRIX */
return row_vector_multiplication(vec1, (MatrixObject*)v2);
} else if (QuaternionObject_Check(v2)) {
- QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */
-
+ QuaternionObject *quat = (QuaternionObject*)v2;
if(vec1->size != 3) {
PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
return NULL;
@@ -828,9 +757,6 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
int i;
float scalar;
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
/* only support vec*=float and vec*=mat
vec*=vec result is a float so that wont work */
if (MatrixObject_Check(v2)) {
@@ -838,9 +764,6 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
int x,y, size = vec->size;
MatrixObject *mat= (MatrixObject*)v2;
- if(!BaseMath_ReadCallback(mat))
- return NULL;
-
if(mat->colSize != size){
if(mat->rowSize == 4 && vec->size != 3){
PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
@@ -864,21 +787,22 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
}
vec->vec[i] = (float)dot;
}
+ Py_INCREF( v1 );
+ return v1;
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
for(i = 0; i < vec->size; i++) {
vec->vec[i] *= scalar;
}
- }
- else {
- PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
- return NULL;
+
+ Py_INCREF( v1 );
+ return v1;
+
}
- BaseMath_WriteCallback(vec);
- Py_INCREF( v1 );
- return v1;
+ PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
+ return NULL;
}
/*------------------------obj / obj------------------------------
@@ -895,9 +819,6 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2)
}
vec1 = (VectorObject*)v1; /* vector */
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
-
scalar = (float)PyFloat_AsDouble(v2);
if(scalar== -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
@@ -921,10 +842,14 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
{
int i;
float scalar;
- VectorObject *vec1 = (VectorObject*)v1;
+ VectorObject *vec1 = NULL;
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
+ /*if(!VectorObject_Check(v1)) {
+ PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
+ return -1;
+ }*/
+
+ vec1 = (VectorObject*)v1; /* vector */
scalar = (float)PyFloat_AsDouble(v2);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
@@ -939,9 +864,6 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] /= scalar;
}
-
- BaseMath_WriteCallback(vec1);
-
Py_INCREF( v1 );
return v1;
}
@@ -952,10 +874,6 @@ static PyObject *Vector_neg(VectorObject *self)
{
int i;
float vec[4];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
for(i = 0; i < self->size; i++){
vec[i] = -self->vec[i];
}
@@ -1001,9 +919,6 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
vecA = (VectorObject*)objectA;
vecB = (VectorObject*)objectB;
- if(!BaseMath_ReadCallback(vecA) || !BaseMath_ReadCallback(vecB))
- return NULL;
-
if (vecA->size != vecB->size){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
@@ -1077,44 +992,6 @@ static PySequenceMethods Vector_SeqMethods = {
(ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */
};
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Vector_NumMethods = {
- (binaryfunc) Vector_add, /*nb_add*/
- (binaryfunc) Vector_sub, /*nb_subtract*/
- (binaryfunc) Vector_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) Vector_neg, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) 0, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- Vector_iadd, /* nb_inplace_add */
- Vector_isub, /* nb_inplace_subtract */
- Vector_imul, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- Vector_div, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- Vector_idiv, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
static PyNumberMethods Vector_NumMethods = {
(binaryfunc) Vector_add, /* __add__ */
(binaryfunc) Vector_sub, /* __sub__ */
@@ -1160,8 +1037,6 @@ static PyNumberMethods Vector_NumMethods = {
(binaryfunc) NULL, /*__ifloordiv__*/
(binaryfunc) NULL, /*__itruediv__*/
};
-#endif
-
/*------------------PY_OBECT DEFINITION--------------------------*/
/*
@@ -1170,12 +1045,66 @@ static PyNumberMethods Vector_NumMethods = {
static PyObject *Vector_getAxis( VectorObject * self, void *type )
{
- return Vector_item(self, GET_INT_FROM_POINTER(type));
+ switch( (long)type ) {
+ case 'X': /* these are backwards, but that how it works */
+ return PyFloat_FromDouble(self->vec[0]);
+ case 'Y':
+ return PyFloat_FromDouble(self->vec[1]);
+ case 'Z': /* these are backwards, but that how it works */
+ if(self->size < 3) {
+ PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
+ return NULL;
+ }
+ else {
+ return PyFloat_FromDouble(self->vec[2]);
+ }
+ case 'W':
+ if(self->size < 4) {
+ PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
+ return NULL;
+ }
+
+ return PyFloat_FromDouble(self->vec[3]);
+ default:
+ {
+ PyErr_SetString( PyExc_RuntimeError, "undefined type in Vector_getAxis" );
+ return NULL;
+ }
+ }
}
static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
{
- return Vector_ass_item(self, GET_INT_FROM_POINTER(type), value);
+ float param= (float)PyFloat_AsDouble( value );
+
+ if (param==-1 && PyErr_Occurred()) {
+ PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+ return -1;
+ }
+ switch( (long)type ) {
+ case 'X': /* these are backwards, but that how it works */
+ self->vec[0]= param;
+ break;
+ case 'Y':
+ self->vec[1]= param;
+ break;
+ case 'Z': /* these are backwards, but that how it works */
+ if(self->size < 3) {
+ PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
+ return -1;
+ }
+ self->vec[2]= param;
+ break;
+ case 'W':
+ if(self->size < 4) {
+ PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
+ return -1;
+ }
+ self->vec[3]= param;
+ break;
+ }
+
+ return 0;
}
/* vector.length */
@@ -1184,9 +1113,6 @@ static PyObject *Vector_getLength( VectorObject * self, void *type )
double dot = 0.0f;
int i;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
for(i = 0; i < self->size; i++){
dot += (self->vec[i] * self->vec[i]);
}
@@ -1198,9 +1124,6 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
double dot = 0.0f, param;
int i;
- if(!BaseMath_ReadCallback(self))
- return -1;
-
param= PyFloat_AsDouble( value );
if(param==-1.0 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "length must be set to a number");
@@ -1236,11 +1159,18 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
self->vec[i]= self->vec[i] / (float)dot;
}
- BaseMath_WriteCallback(self); /* checked alredy */
-
return 0;
}
+static PyObject *Vector_getWrapped( VectorObject * self, void *type )
+{
+ if (self->wrapped == Py_WRAP)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+
/* Get a new Vector according to the provided swizzle. This function has little
error checking, as we are in control of the inputs: the closure is set by us
in Vector_createSwizzleGetSeter. */
@@ -1251,9 +1181,6 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure)
float vec[MAX_DIMENSIONS];
unsigned int swizzleClosure;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
/* Unpack the axes from the closure into an array. */
axisA = 0;
swizzleClosure = (unsigned int) closure;
@@ -1291,9 +1218,6 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
float vecTemp[MAX_DIMENSIONS];
- if(!BaseMath_ReadCallback(self))
- return -1;
-
/* Check that the closure can be used with this vector: even 2D vectors have
swizzles defined for axes z and w, but they would be invalid. */
swizzleClosure = (unsigned int) closure;
@@ -1323,7 +1247,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
axisB++;
}
memcpy(self->vec, vecTemp, axisB * sizeof(float));
- /* continue with BaseMathObject_WriteCallback at the end */
+ return 0;
}
else if (PyList_Check(value))
{
@@ -1349,7 +1273,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
axisB++;
}
memcpy(self->vec, vecTemp, axisB * sizeof(float));
- /* continue with BaseMathObject_WriteCallback at the end */
+ return 0;
}
else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0)
{
@@ -1362,17 +1286,13 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
}
- /* continue with BaseMathObject_WriteCallback at the end */
+ return 0;
}
- else {
+ else
+ {
PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." );
return -1;
}
-
- if(!BaseMath_WriteCallback(vecVal))
- return -1;
- else
- return 0;
}
/*****************************************************************************/
@@ -1382,19 +1302,19 @@ static PyGetSetDef Vector_getseters[] = {
{"x",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector X axis",
- (void *)0},
+ (void *)'X'},
{"y",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Y axis",
- (void *)1},
+ (void *)'Y'},
{"z",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Z axis",
- (void *)2},
+ (void *)'Z'},
{"w",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Z axis",
- (void *)3},
+ (void *)'W'},
{"length",
(getter)Vector_getLength, (setter)Vector_setLength,
"Vector Length",
@@ -1404,13 +1324,9 @@ static PyGetSetDef Vector_getseters[] = {
"Vector Length",
NULL},
{"wrapped",
- (getter)BaseMathObject_getWrapped, (setter)NULL,
+ (getter)Vector_getWrapped, (setter)NULL,
"True when this wraps blenders internal data",
NULL},
- {"__owner__",
- (getter)BaseMathObject_getOwner, (setter)NULL,
- "Read only owner for vectors that depend on another object",
- NULL},
/* autogenerated swizzle attrs, see python script below */
{"xx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 36 */
@@ -1811,13 +1727,13 @@ PyTypeObject vector_Type = {
0, /* ob_size */
#endif
/* For printing, in format "<module>.<name>" */
- "vector", /* char *tp_name; */
+ "Blender Vector", /* char *tp_name; */
sizeof( VectorObject ), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
- ( destructor ) BaseMathObject_dealloc,/* destructor tp_dealloc; */
+ ( destructor ) Vector_dealloc,/* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
@@ -1903,10 +1819,6 @@ PyObject *newVectorObject(float *vec, int size, int type)
if(size > 4 || size < 2)
return NULL;
self->size = size;
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP) {
self->vec = vec;
@@ -1931,72 +1843,20 @@ PyObject *newVectorObject(float *vec, int size, int type)
return (PyObject *) self;
}
-PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype)
-{
- float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */
- VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
-
-//-----------------row_vector_multiplication (internal)-----------
-//ROW VECTOR Multiplication - Vector X Matrix
-//[x][y][z] * [1][2][3]
-// [4][5][6]
-// [7][8][9]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
-{
- float vecNew[4], vecCopy[4];
- double dot = 0.0f;
- int x, y, z = 0, vec_size = vec->size;
-
- if(mat->colSize != vec_size){
- if(mat->rowSize == 4 && vec_size != 3){
- PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
- return NULL;
- }else{
- vecCopy[3] = 1.0f;
- }
- }
-
- if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
- return NULL;
-
- for(x = 0; x < vec_size; x++){
- vecCopy[x] = vec->vec[x];
- }
-
- //muliplication
- for(x = 0; x < mat->colSize; x++) {
- for(y = 0; y < mat->rowSize; y++) {
- dot += mat->matrix[y][x] * vecCopy[y];
- }
- vecNew[z++] = (float)dot;
- dot = 0.0f;
- }
- return newVectorObject(vecNew, vec_size, Py_NEW);
-}
-
-/*----------------------------Vector.negate() --------------------
+/*
+ #############################DEPRECATED################################
+ #######################################################################
+ ----------------------------Vector.negate() --------------------
set the vector to it's negative -x, -y, -z */
static PyObject *Vector_Negate(VectorObject * self)
{
int i;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++)
+ for(i = 0; i < self->size; i++) {
self->vec[i] = -(self->vec[i]);
-
- BaseMath_WriteCallback(self); // alredy checked for error
-
+ }
+ /*printf("Vector.negate(): Deprecated: use -vector instead\n");*/
Py_INCREF(self);
return (PyObject*)self;
}
+/*###################################################################
+ ###########################DEPRECATED##############################*/
diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h
index f519b2808cb..d2eb826ef10 100644
--- a/source/blender/python/generic/vector.h
+++ b/source/blender/python/generic/vector.h
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: vector.h 20332 2009-05-22 03:22:56Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -37,20 +37,14 @@ extern PyTypeObject vector_Type;
#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type)
-typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
+typedef struct {
PyObject_VAR_HEAD
- float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
- unsigned char size; /* vec size 2,3 or 4 */
+ float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
+ short size; /* vec size 2,3 or 4 */
+ short wrapped; /* is wrapped data? */
} VectorObject;
/*prototypes*/
PyObject *newVectorObject(float *vec, int size, int type);
-PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
#endif /* EXPP_vector_h */
diff --git a/source/blender/python/intern/Makefile b/source/blender/python/intern/Makefile
index d210cfaf973..0c4a540a4bd 100644
--- a/source/blender/python/intern/Makefile
+++ b/source/blender/python/intern/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/python/intern/bpy_compat.h b/source/blender/python/intern/bpy_compat.h
index 1ad9376c13b..032b60988d5 100644
--- a/source/blender/python/intern/bpy_compat.h
+++ b/source/blender/python/intern/bpy_compat.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_compat.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 8b5ad36f349..559ed537757 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -37,11 +37,6 @@
#include "BPY_extern.h"
#include "../generic/bpy_internal_import.h" // our own imports
-/* external util modukes */
-
-#include "../generic/Mathutils.h"
-#include "../generic/Geometry.h"
-#include "../generic/BGL.h"
void BPY_free_compiled_text( struct Text *text )
@@ -66,17 +61,11 @@ static void bpy_init_modules( void )
PyModule_AddObject( mod, "types", BPY_rna_types() );
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "ops", BPY_operator_module() );
- PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
+ PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
Py_DECREF(mod);
-
-
- /* stand alone utility modules not related to blender directly */
- Geometry_Init("Geometry");
- Mathutils_Init("Mathutils");
- BGL_Init("BGL");
}
#if (PY_VERSION_HEX < 0x02050000)
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 004cf2fb7c7..3ea330adc85 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_operator.h b/source/blender/python/intern/bpy_operator.h
index 46ea144fd4d..8a4493b5866 100644
--- a/source/blender/python/intern/bpy_operator.h
+++ b/source/blender/python/intern/bpy_operator.h
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index b7e3c86dd91..3d5427ddefd 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator_wrap.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -47,6 +47,98 @@
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
+static PyObject *pyop_dict_from_event(wmEvent *event)
+{
+ PyObject *dict= PyDict_New();
+ PyObject *item;
+ char *cstring, ascii[2];
+
+ /* type */
+ item= PyUnicode_FromString(WM_key_event_string(event->type));
+ PyDict_SetItemString(dict, "type", item); Py_DECREF(item);
+
+ /* val */
+ switch(event->val) {
+ case KM_ANY:
+ cstring = "ANY";
+ break;
+ case KM_RELEASE:
+ cstring = "RELEASE";
+ break;
+ case KM_PRESS:
+ cstring = "PRESS";
+ break;
+ default:
+ cstring = "UNKNOWN";
+ break;
+ }
+
+ item= PyUnicode_FromString(cstring);
+ PyDict_SetItemString(dict, "val", item); Py_DECREF(item);
+
+ /* x, y (mouse) */
+ item= PyLong_FromLong(event->x);
+ PyDict_SetItemString(dict, "x", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->y);
+ PyDict_SetItemString(dict, "y", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->prevx);
+ PyDict_SetItemString(dict, "prevx", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->prevy);
+ PyDict_SetItemString(dict, "prevy", item); Py_DECREF(item);
+
+ /* ascii */
+ ascii[0]= event->ascii;
+ ascii[1]= '\0';
+ item= PyUnicode_FromString(ascii);
+ PyDict_SetItemString(dict, "ascii", item); Py_DECREF(item);
+
+ /* modifier keys */
+ item= PyLong_FromLong(event->shift);
+ PyDict_SetItemString(dict, "shift", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->ctrl);
+ PyDict_SetItemString(dict, "ctrl", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->alt);
+ PyDict_SetItemString(dict, "alt", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->oskey);
+ PyDict_SetItemString(dict, "oskey", item); Py_DECREF(item);
+
+
+
+ /* modifier */
+#if 0
+ item= PyTuple_New(0);
+ if(event->keymodifier & KM_SHIFT) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
+ size++;
+ }
+ if(event->keymodifier & KM_CTRL) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
+ size++;
+ }
+ if(event->keymodifier & KM_ALT) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
+ size++;
+ }
+ if(event->keymodifier & KM_OSKEY) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
+ size++;
+ }
+ PyDict_SetItemString(dict, "keymodifier", item); Py_DECREF(item);
+#endif
+
+ return dict;
+}
+
static struct BPY_flag_def pyop_ret_flags[] = {
{"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
{"CANCELLED", OPERATOR_CANCELLED},
@@ -88,7 +180,6 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
PointerRNA ptr_context;
PointerRNA ptr_operator;
- PointerRNA ptr_event;
PyObject *py_operator;
PyGILState_STATE gilstate = PyGILState_Ensure();
@@ -107,9 +198,15 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
/* Assign instance attributes from operator properties */
{
+ PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
const char *arg_name;
- RNA_STRUCT_BEGIN(op->ptr, prop) {
+ iterprop= RNA_struct_iterator_property(op->ptr->type);
+ RNA_property_collection_begin(op->ptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -118,7 +215,8 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PyObject_SetAttrString(py_class_instance, arg_name, item);
Py_DECREF(item);
}
- RNA_STRUCT_END;
+
+ RNA_property_collection_end(&iter);
}
/* set operator pointer RNA as instance "__operator__" attribute */
@@ -132,13 +230,11 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
if (mode==PYOP_INVOKE) {
item= PyObject_GetAttrString(py_class, "invoke");
args = PyTuple_New(3);
-
- RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
// PyTuple_SET_ITEM "steals" object reference, it is
// an object passed shouldn't be DECREF'ed
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
- PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event));
+ PyTuple_SET_ITEM(args, 2, pyop_dict_from_event(event));
}
else if (mode==PYOP_EXEC) {
item= PyObject_GetAttrString(py_class, "execute");
diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h
index 2929d57ab82..c9efb1ea22f 100644
--- a/source/blender/python/intern/bpy_operator_wrap.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator_wrap.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index f07c85f7083..d131361294d 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_rna.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -39,94 +39,6 @@
#include "BKE_global.h" /* evil G.* */
#include "BKE_report.h"
-#define USE_MATHUTILS
-
-#ifdef USE_MATHUTILS
-#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
-
-/* bpyrna vector/euler/quat callbacks */
-static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_rna_generic_check(BPy_PropertyRNA *self)
-{
- return self->prop?1:0;
-}
-
-static int mathutils_rna_vector_get(BPy_PropertyRNA *self, int subtype, float *vec_from)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_get_array(&self->ptr, self->prop, vec_from);
- return 1;
-}
-
-static int mathutils_rna_vector_set(BPy_PropertyRNA *self, int subtype, float *vec_to)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_array(&self->ptr, self->prop, vec_to);
- return 1;
-}
-
-static int mathutils_rna_vector_get_index(BPy_PropertyRNA *self, int subtype, float *vec_from, int index)
-{
- if(self->prop==NULL)
- return 0;
-
- vec_from[index]= RNA_property_float_get_index(&self->ptr, self->prop, index);
- return 1;
-}
-
-static int mathutils_rna_vector_set_index(BPy_PropertyRNA *self, int subtype, float *vec_to, int index)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_index(&self->ptr, self->prop, index, vec_to[index]);
- return 1;
-}
-
-Mathutils_Callback mathutils_rna_array_cb = {
- mathutils_rna_generic_check,
- mathutils_rna_vector_get,
- mathutils_rna_vector_set,
- mathutils_rna_vector_get_index,
- mathutils_rna_vector_set_index
-};
-
-/* bpyrna matrix callbacks */
-static int mathutils_rna_matrix_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_rna_matrix_get(BPy_PropertyRNA *self, int subtype, float *mat_from)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_get_array(&self->ptr, self->prop, mat_from);
- return 1;
-}
-
-static int mathutils_rna_matrix_set(BPy_PropertyRNA *self, int subtype, float *mat_to)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_array(&self->ptr, self->prop, mat_to);
- return 1;
-}
-
-Mathutils_Callback mathutils_rna_matrix_cb = {
- mathutils_rna_generic_check,
- mathutils_rna_matrix_get,
- mathutils_rna_matrix_set,
- NULL,
- NULL
-};
-
-#endif
-
static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b )
{
return (a->ptr.data==b->ptr.data) ? 0 : -1;
@@ -161,15 +73,14 @@ static PyObject *pyrna_prop_richcmp(BPy_PropertyRNA * a, BPy_PropertyRNA * b, in
/*----------------------repr--------------------------------------------*/
static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
{
- PyObject *pyob;
- char *name;
+ PropertyRNA *prop;
+ char str[512];
/* print name if available */
- name= RNA_struct_name_get_alloc(&self->ptr, NULL, 0);
- if(name) {
- pyob= PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), name);
- MEM_freeN(name);
- return pyob;
+ prop= RNA_struct_name_property(self->ptr.type);
+ if(prop) {
+ RNA_property_string_get(&self->ptr, prop, str);
+ return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), str);
}
return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\"]", RNA_struct_identifier(self->ptr.type));
@@ -177,19 +88,20 @@ static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
{
- PyObject *pyob;
+ PropertyRNA *prop;
PointerRNA ptr;
- char *name;
+ char str[512];
/* if a pointer, try to print name of pointer target too */
if(RNA_property_type(self->prop) == PROP_POINTER) {
ptr= RNA_property_pointer_get(&self->ptr, self->prop);
- name= RNA_struct_name_get_alloc(&ptr, NULL, 0);
- if(name) {
- pyob= PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), name);
- MEM_freeN(name);
- return pyob;
+ if(ptr.data) {
+ prop= RNA_struct_name_property(ptr.type);
+ if(prop) {
+ RNA_property_string_get(&ptr, prop, str);
+ return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), str);
+ }
}
}
@@ -204,13 +116,13 @@ static long pyrna_struct_hash( BPy_StructRNA * self )
/* use our own dealloc so we can free a property if we use one */
static void pyrna_struct_dealloc( BPy_StructRNA * self )
{
+ /* Note!! for some weired reason calling PyObject_DEL() directly crashes blender! */
if (self->freeptr && self->ptr.data) {
IDP_FreeProperty(self->ptr.data);
MEM_freeN(self->ptr.data);
self->ptr.data= NULL;
}
- /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */
Py_TYPE(self)->tp_free(self);
return;
}
@@ -218,8 +130,9 @@ static void pyrna_struct_dealloc( BPy_StructRNA * self )
static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
{
const EnumPropertyItem *item;
+ int totitem;
- RNA_property_enum_items(ptr, prop, &item, NULL);
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
return (char*)BPy_enum_as_string((EnumPropertyItem*)item);
}
@@ -231,52 +144,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
if (len > 0) {
/* resolve the array from a new pytype */
- PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop);
-
-#ifdef USE_MATHUTILS
-
- /* return a mathutils vector where possible */
- if(RNA_property_type(prop)==PROP_FLOAT) {
- switch(RNA_property_subtype(prop)) {
- case PROP_VECTOR:
- if(len>=2 && len <= 4) {
- PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the vector owns now */
- ret= vec_cb; /* return the vector instead */
- }
- break;
- case PROP_MATRIX:
- if(len==16) {
- PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= mat_cb; /* return the matrix instead */
- }
- else if (len==9) {
- PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= mat_cb; /* return the matrix instead */
- }
- break;
- case PROP_ROTATION:
- if(len==3) { /* euler */
- PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= eul_cb; /* return the matrix instead */
- }
- else if (len==4) {
- PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= quat_cb; /* return the matrix instead */
- }
- break;
- default:
- break;
- }
- }
-
-#endif
-
- return ret;
+ return pyrna_prop_CreatePyObject(ptr, prop);
}
/* see if we can coorce into a python type - PropertyType */
@@ -345,9 +213,17 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
const char *arg_name= NULL;
PyObject *item;
+ PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+
totkw = kw ? PyDict_Size(kw):0;
- RNA_STRUCT_BEGIN(ptr, prop) {
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
+
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -373,7 +249,8 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
totkw--;
}
- RNA_STRUCT_END;
+
+ RNA_property_collection_end(&iter);
if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */
PyObject *key, *value;
@@ -394,15 +271,12 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw);
-PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func)
+PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func)
{
static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"};
PyObject *self= PyTuple_New(2);
PyObject *ret;
-
- PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna);
- Py_INCREF(pyrna);
-
+ PyTuple_SET_ITEM(self, 0, pyrna_struct_CreatePyObject(ptr));
PyTuple_SET_ITEM(self, 1, PyCObject_FromVoidPtr((void *)func, NULL));
ret= PyCFunction_New(&func_meth, self);
@@ -420,30 +294,15 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if (len > 0) {
PyObject *item;
- int py_len = -1;
int i;
-
-#ifdef USE_MATHUTILS
- if(MatrixObject_Check(value)) {
- MatrixObject *mat = (MatrixObject*)value;
- if(!BaseMath_ReadCallback(mat))
- return -1;
-
- py_len = mat->rowSize * mat->colSize;
- } else /* continue... */
-#endif
- if (PySequence_Check(value)) {
- py_len= (int)PySequence_Length(value);
- }
- else {
- PyErr_Format(PyExc_TypeError, "RNA array assignment expected a sequence instead of %s instance.", Py_TYPE(value)->tp_name);
+ if (!PySequence_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array.");
return -1;
}
- /* done getting the length */
- if (py_len != len) {
- PyErr_Format(PyExc_AttributeError, "python sequence length %d did not match the RNA array length %d.", py_len, len);
+ if ((int)PySequence_Length(value) != len) {
+ PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array.");
return -1;
}
@@ -509,21 +368,14 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
else param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array");
-#ifdef USE_MATHUTILS
- if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) {
- MatrixObject *mat = (MatrixObject*)value;
- memcpy(param_arr, mat->contigPtr, sizeof(float) * len);
- } else /* continue... */
-#endif
- {
- /* collect the variables */
- for (i=0; i<len; i++) {
- item = PySequence_GetItem(value, i);
- param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
- Py_DECREF(item);
- }
+
+ /* collect the variables */
+ for (i=0; i<len; i++) {
+ item = PySequence_GetItem(value, i);
+ param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
+ Py_DECREF(item);
}
-
+
if (PyErr_Occurred()) {
if(data==NULL)
MEM_freeN(param_arr);
@@ -679,10 +531,6 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
int seq_len, i;
PyObject *item;
PointerRNA itemptr;
- ListBase *lb;
- CollectionPointerLink *link;
-
- lb= (data)? (ListBase*)data: NULL;
/* convert a sequence of dict's into a collection */
if(!PySequence_Check(value)) {
@@ -698,15 +546,8 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
Py_XDECREF(item);
return -1;
}
-
- if(lb) {
- link= MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink");
- link->ptr= itemptr;
- BLI_addtail(lb, link);
- }
- else
- RNA_property_collection_add(ptr, prop, &itemptr);
-
+
+ RNA_property_collection_add(ptr, prop, &itemptr);
if(pyrna_pydict_to_props(&itemptr, item, "Converting a python list to an RNA collection")==-1) {
Py_DECREF(item);
return -1;
@@ -963,6 +804,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
PyObject *pystring;
/* for looping over attrs and funcs */
+ CollectionPropertyIterator iter;
PropertyRNA *iterprop;
/* Include this incase this instance is a subtype of a python class
@@ -991,23 +833,26 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
/*
* Collect RNA attributes
*/
+ PropertyRNA *nameprop;
char name[256], *nameptr;
iterprop= RNA_struct_iterator_property(self->ptr.type);
+ RNA_property_collection_begin(&self->ptr, iterprop, &iter);
- RNA_PROP_BEGIN(&self->ptr, itemptr, iterprop) {
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
-
- if(nameptr) {
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
+
pystring = PyUnicode_FromString(nameptr);
PyList_Append(ret, pystring);
Py_DECREF(pystring);
- if(name != nameptr)
+ if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
+
}
@@ -1020,12 +865,15 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
RNA_pointer_create(NULL, &RNA_Struct, self->ptr.type, &tptr);
iterprop= RNA_struct_find_property(&tptr, "functions");
- RNA_PROP_BEGIN(&tptr, itemptr, iterprop) {
- pystring = PyUnicode_FromString(RNA_function_identifier(itemptr.data));
+ RNA_property_collection_begin(&tptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ pystring = PyUnicode_FromString(RNA_function_identifier(iter.ptr.data));
PyList_Append(ret, pystring);
Py_DECREF(pystring);
}
- RNA_PROP_END;
+
+ RNA_property_collection_end(&iter);
}
if(self->ptr.type == &RNA_Context) {
@@ -1067,7 +915,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
ret = pyrna_prop_to_py(&self->ptr, prop);
}
else if ((func = RNA_struct_find_function(&self->ptr, name))) {
- ret = pyrna_func_to_py(self, func);
+ ret = pyrna_func_to_py(&self->ptr, func);
}
else if (self->ptr.type == &RNA_Context) {
PointerRNA newptr;
@@ -1138,25 +986,28 @@ PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *nameprop;
char name[256], *nameptr;
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
-
- if(nameptr) {
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
+
/* add to python list */
item = PyUnicode_FromString( nameptr );
PyList_Append(ret, item);
Py_DECREF(item);
/* done */
- if(name != nameptr)
+ if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
}
return ret;
@@ -1170,25 +1021,28 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *nameprop;
char name[256], *nameptr;
int i= 0;
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- if(itemptr.data) {
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data) {
/* add to python list */
item= PyTuple_New(2);
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
- if(nameptr) {
+ if(nameprop = RNA_struct_name_property(iter.ptr.type)) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr ));
- if(name != nameptr)
+ if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
else {
PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */
}
- PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr));
+ PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&iter.ptr));
PyList_Append(ret, item);
Py_DECREF(item);
@@ -1196,7 +1050,7 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
i++;
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
}
return ret;
@@ -1212,14 +1066,18 @@ PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- item = pyrna_struct_CreatePyObject(&itemptr);
+ //iterprop= RNA_struct_iterator_property(self->ptr.type);
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ item = pyrna_struct_CreatePyObject(&iter.ptr);
PyList_Append(ret, item);
Py_DECREF(item);
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
}
return ret;
@@ -1393,21 +1251,10 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
break;
}
case PROP_COLLECTION:
- {
- ListBase *lb= (ListBase*)data;
- CollectionPointerLink *link;
- PyObject *linkptr;
-
- ret = PyList_New(0);
-
- for(link=lb->first; link; link=link->next) {
- linkptr= pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
- }
-
+ /* XXX not supported yet
+ * ret = pyrna_prop_CreatePyObject(ptr, prop); */
+ ret = NULL;
break;
- }
default:
PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type);
ret = NULL;
@@ -1827,11 +1674,6 @@ PyObject *BPY_rna_module( void )
{
PointerRNA ptr;
-#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once.
- mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb);
- mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb);
-#endif
-
/* This can't be set in the pytype struct because some compilers complain */
pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr;
pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr;
@@ -2041,7 +1883,7 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
char *id, *name="", *description="";
int def=0;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def))
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:IntProperty", kwlist, &id, &name, &description, &def))
return NULL;
if (PyTuple_Size(args) > 0) {
@@ -2055,7 +1897,7 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
} else {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_BoolProperty, NULL));
+ PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_IntProperty, NULL));
PyTuple_SET_ITEM(ret, 1, kw);
Py_INCREF(kw);
return ret;
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index d2f01b06336..45614e992c6 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_rna.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
index 088fe436c69..ccc8b2c206a 100644
--- a/source/blender/python/intern/bpy_ui.c
+++ b/source/blender/python/intern/bpy_ui.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_ui.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_ui.h b/source/blender/python/intern/bpy_ui.h
index 4182a32d3f0..be5e5e87015 100644
--- a/source/blender/python/intern/bpy_ui.h
+++ b/source/blender/python/intern/bpy_ui.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_ui.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index bce73b903c0..6ec01e0c3fc 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_util.c 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -171,7 +171,7 @@ void PyObSpit(char *name, PyObject *var) {
else {
PyObject_Print(var, stderr, 0);
fprintf(stderr, " ref:%d ", var->ob_refcnt);
- fprintf(stderr, " ptr:%p", (void *)var);
+ fprintf(stderr, " ptr:%ld", (long)var);
fprintf(stderr, " type:");
if(Py_TYPE(var))
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index 6429af67eb0..bc87da75de6 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_util.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/radiosity/CMakeLists.txt b/source/blender/radiosity/CMakeLists.txt
new file mode 100644
index 00000000000..e76f7409f99
--- /dev/null
+++ b/source/blender/radiosity/CMakeLists.txt
@@ -0,0 +1,36 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC intern/source/*.c)
+
+SET(INC
+ extern/include ../blenlib ../blenkernel ../makesdna ../editors/include
+ ../../../intern/guardedalloc ../render/extern/include
+ ../render/intern/include ../blenloader ../../../extern/glew/include
+)
+
+BLENDERLIB_NOLIST(blender_radiosity "${SRC}" "${INC}")
+#env.BlenderLib ( 'blender_radiosity', sources, Split(incs), [], libtype='core', priority=50 )
diff --git a/source/blender/radiosity/Makefile b/source/blender/radiosity/Makefile
new file mode 100644
index 00000000000..91a13e2fd57
--- /dev/null
+++ b/source/blender/radiosity/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/SConscript b/source/blender/radiosity/SConscript
new file mode 100644
index 00000000000..29854d2ee83
--- /dev/null
+++ b/source/blender/radiosity/SConscript
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('intern/source/*.c')
+
+incs = 'extern/include ../blenlib ../blenkernel ../makesdna ../editors/include'
+incs += ' #/intern/guardedalloc ../render/extern/include'
+incs += ' ../render/intern/include ../blenloader #/extern/glew/include'
+
+incs += ' ' + env['BF_OPENGL_INC']
+
+env.BlenderLib ( 'bf_radiosity', sources, Split(incs), [], libtype='core', priority=150 )
diff --git a/source/blender/radiosity/extern/include/radio.h b/source/blender/radiosity/extern/include/radio.h
new file mode 100644
index 00000000000..e7f23302880
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio.h
@@ -0,0 +1,173 @@
+/* ***************************************
+
+
+
+ radio.h nov/dec 1992
+ revised for Blender may 1999
+
+ $Id$
+
+ ***** BEGIN GPL LICENSE BLOCK *****
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ All rights reserved.
+
+ The Original Code is: all of this file.
+
+ Contributor(s): none yet.
+
+ ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef RADIO_H
+#define RADIO_H
+#define RADIO_H
+
+/* type include */
+#include "radio_types.h"
+
+extern RadGlobal RG;
+struct View3D;
+struct Scene;
+
+/* radfactors.c */
+extern float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area);
+extern void calcTopfactors(void);
+void calcSidefactors(void);
+extern void initradiosity(void);
+extern void rad_make_hocos(RadView *vw);
+extern void hemizbuf(RadView *vw);
+extern int makeformfactors(RPatch *shoot);
+extern void applyformfactors(RPatch *shoot);
+extern RPatch *findshootpatch(void);
+extern void setnodeflags(RNode *rn, int flag, int set);
+extern void backface_test(RPatch *shoot);
+extern void clear_backface_test(void);
+extern void progressiverad(void);
+extern void minmaxradelem(RNode *rn, float *min, float *max);
+extern void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax);
+extern void subdivideshootElements(int it);
+extern void subdivideshootPatches(int it);
+extern void inithemiwindows(void);
+extern void closehemiwindows(void);
+void rad_init_energy(void);
+
+/* radio.c */
+void freeAllRad(struct Scene *scene);
+int rad_phase(void);
+void rad_status_str(char *str);
+void rad_printstatus(void);
+void rad_setlimits(struct Scene *scene);
+void set_radglobal(struct Scene *scene);
+void add_radio(struct Scene *scene);
+void delete_radio(struct Scene *scene);
+int rad_go(struct Scene *scene);
+void rad_subdivshootpatch(struct Scene *scene);
+void rad_subdivshootelem(struct Scene *scene);
+void rad_limit_subdivide(struct Scene *scene);
+
+/* radnode.c */
+extern void setnodelimit(float limit);
+extern float *mallocVert(void);
+extern float *callocVert(void);
+extern void freeVert(float *vert);
+extern int totalRadVert(void);
+extern RNode *mallocNode(void);
+extern RNode *callocNode(void);
+extern void freeNode(RNode *node);
+extern void freeNode_recurs(RNode *node);
+extern RPatch *mallocPatch(void);
+extern RPatch *callocPatch(void);
+extern void freePatch(RPatch *patch);
+extern void replaceAllNode(RNode *, RNode *);
+extern void replaceAllNodeInv(RNode *neighb, RNode *old);
+extern void replaceAllNodeUp(RNode *neighb, RNode *old);
+extern void replaceTestNode(RNode *, RNode **, RNode *, int , float *);
+extern void free_fastAll(void);
+
+/* radnode.c */
+extern void start_fastmalloc(char *str);
+extern int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2);
+extern float edlen(float *v1, float *v2);
+extern void deleteNodes(RNode *node);
+extern void subdivideTriNode(RNode *node, RNode *edge);
+extern void subdivideNode(RNode *node, RNode *edge);
+extern int comparelevel(RNode *node, RNode *nb, int level);
+
+/* radpreprocess.c */
+extern void splitconnected(void);
+extern int vergedge(const void *v1,const void *v2);
+extern void addedge(float *v1, float *v2, EdSort *es);
+extern void setedgepointers(void);
+extern void rad_collect_meshes(struct Scene *scene, struct View3D *v3d);
+extern void countelem(RNode *rn);
+extern void countglobaldata(void);
+extern void addelem(RNode ***el, RNode *rn, RPatch *rp);
+extern void makeGlobalElemArray(void);
+extern void remakeGlobaldata(void);
+extern void splitpatch(RPatch *old);
+extern void addpatch(RPatch *old, RNode *rn);
+extern void converttopatches(void);
+extern void make_elements(void);
+extern void subdividelamps(void);
+extern void maxsizePatches(void);
+extern void subdiv_elements(void);
+
+/* radpostprocess.c */
+void addaccu(register char *z, register char *t);
+void addaccuweight(register char *z, register char *t, int w);
+void triaweight(Face *face, int *w1, int *w2, int *w3);
+void init_face_tab(void);
+Face *addface(void);
+Face *makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn);
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag);
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag);
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2);
+void make_face_tab(void);
+void filterFaces(void);
+void calcfiltrad(RNode *rn, float *cd);
+void filterNodes(void);
+void removeEqualNodes(short limit);
+void rad_addmesh(struct Scene *scene);
+void rad_replacemesh(struct Scene *scene);
+
+/* raddisplay.c */
+extern char calculatecolor(float col);
+extern void make_node_display(void);
+extern void drawnodeWire(RNode *rn);
+extern void drawsingnodeWire(RNode *rn);
+extern void drawnodeSolid(RNode *rn);
+extern void drawnodeGour(RNode *rn);
+extern void drawpatch(RPatch *patch, unsigned int col);
+extern void drawfaceGour(Face *face);
+extern void drawfaceSolid(Face *face);
+extern void drawfaceWire(Face *face);
+extern void drawsquare(float *cent, float size, short cox, short coy);
+extern void drawlimits(void);
+extern void setcolNode(RNode *rn, unsigned int *col);
+extern void pseudoAmb(void);
+extern void rad_forcedraw(void);
+extern void drawpatch_ext(RPatch *patch, unsigned int col);
+extern void RAD_drawall(int depth_is_on);
+
+/* radrender.c */
+struct Render;
+extern void do_radio_render(struct Render *re);
+void end_radio_render(void);
+
+#endif /* RADIO_H */
+
diff --git a/source/blender/radiosity/extern/include/radio_types.h b/source/blender/radiosity/extern/include/radio_types.h
new file mode 100644
index 00000000000..5a218ee71be
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio_types.h
@@ -0,0 +1,168 @@
+/*
+ * radio_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* #include "misc_util.h" */ /* for listbase...*/
+
+
+#ifndef RADIO_TYPES_H
+#define RADIO_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_material_types.h"
+
+struct Render;
+struct CustomData;
+
+#define PI M_PI
+#define RAD_MAXFACETAB 1024
+#define RAD_NEXTFACE(a) if( ((a) & 1023)==0 ) face= RG.facebase[(a)>>10]; else face++;
+
+/* RG.phase */
+#define RAD_SHOOTE 1
+#define RAD_SHOOTP 2
+#define RAD_SOLVE 3
+
+typedef struct RadView {
+ float cam[3], tar[3], up[3];
+ float wx1, wx2, wy1, wy2;
+ float mynear, myfar;
+ float viewmat[4][4], winmat[4][4];
+ unsigned int *rect, *rectz;
+ short rectx, recty;
+ int wid;
+
+} RadView;
+
+/* rn->f */
+#define RAD_PATCH 1
+#define RAD_SHOOT 2
+#define RAD_SUBDIV 4
+#define RAD_BACKFACE 8
+#define RAD_TWOSIDED 16
+
+
+typedef struct RNode { /* length: 104 */
+ struct RNode *down1, *down2, *up;
+ struct RNode *ed1, *ed2, *ed3, *ed4;
+ struct RPatch *par;
+
+ char lev1, lev2, lev3, lev4; /* edgelevels */
+ short type; /* type: 4==QUAD, 3==TRIA */
+ short f;
+ float *v1, *v2, *v3, *v4;
+ float totrad[3], area;
+
+ unsigned int col;
+ int orig; /* index in custom face data */
+} RNode;
+
+
+typedef struct Face { /* length: 52 */
+ float *v1, *v2, *v3, *v4;
+ unsigned int col, matindex;
+ int orig; /* index in custom face data */
+} Face;
+
+/* rp->f1 */
+#define RAD_NO_SPLIT 1
+
+typedef struct RPatch {
+ struct RPatch *next, *prev;
+ RNode *first; /* first node==patch */
+
+ struct Object *from;
+
+ int type; /* 3: TRIA, 4: QUAD */
+ short f, f1; /* flags f: if node, only for subdiv */
+
+ float ref[3], emit[3], unshot[3];
+ float cent[3], norm[3];
+ float area;
+ int matindex;
+
+} RPatch;
+
+
+typedef struct VeNoCo { /* needed for splitconnected */
+ struct VeNoCo *next;
+ float *v;
+ float *n;
+ float *col;
+ int flag;
+} VeNoCo;
+
+
+typedef struct EdSort { /* sort edges */
+ float *v1, *v2;
+ RNode *node;
+ int nr;
+} EdSort;
+
+typedef struct {
+ struct Radio *radio;
+ unsigned int *hemibuf;
+ struct ListBase patchbase;
+ int totpatch, totelem, totvert, totlamp;
+ RNode **elem; /* global array with all pointers */
+ VeNoCo *verts; /* temporal vertices from patches */
+ float *formfactors; /* 1 factor per element */
+ float *topfactors, *sidefactors; /* LUT for delta's */
+ int *index; /* LUT for above LUT */
+ Face **facebase;
+ int totface;
+ float min[3], max[3], size[3], cent[3]; /* world */
+ float maxsize, totenergy;
+ float patchmin, patchmax;
+ float elemmin, elemmax;
+ float radfactor, lostenergy, igamma; /* radfac is in button, radfactor is calculated */
+ int phase;
+ struct Render *re; /* for calling hemizbuf correctly */
+ /* to preserve materials as used before, max 16 */
+ Material *matar[MAXMAT];
+ int totmat;
+
+ /* for preserving face data */
+ int mfdatatot;
+ struct CustomData *mfdata;
+ struct RNode **mfdatanodes;
+
+ /* this part is a copy of struct Radio */
+ short hemires, maxiter;
+ short drawtype, flag; /* bit 0 en 1: show limits */
+ short subshootp, subshoote, nodelim, maxsublamp;
+ int maxnode;
+ float convergence;
+ float radfac, gamma; /* for display */
+
+} RadGlobal;
+
+#endif /* radio_types.h */
+
diff --git a/source/blender/radiosity/intern/Makefile b/source/blender/radiosity/intern/Makefile
new file mode 100644
index 00000000000..456b51cc56e
--- /dev/null
+++ b/source/blender/radiosity/intern/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity/intern
+DIRS = source
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile
new file mode 100644
index 00000000000..44b38de9bae
--- /dev/null
+++ b/source/blender/radiosity/intern/source/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# radiosity uses the render lib
+#
+
+LIBNAME = radiosity
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../
+CPPFLAGS += -I../../../blenloader
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# first /include is my own includes, second are the external includes
+# third is the external interface. there should be a nicer way to say this
+CPPFLAGS += -I../include -I../../../editors/include -I../../extern/include
+CPPFLAGS += -I../../../render/extern/include
+CPPFLAGS += -I../../../render/intern/include
diff --git a/source/blender/radiosity/intern/source/raddisplay.c b/source/blender/radiosity/intern/source/raddisplay.c
new file mode 100644
index 00000000000..ab9e8eedc28
--- /dev/null
+++ b/source/blender/radiosity/intern/source/raddisplay.c
@@ -0,0 +1,477 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ raddisplay.c nov/dec 1992
+ may 1999
+
+ - drawing
+ - color calculation for display during solving
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "BLI_blenlib.h"
+
+#include "DNA_radio_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+
+#include "radio.h"
+
+/* cpack has to be endian-insensitive! (old irisgl function) */
+#define cpack(x) glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) )
+
+char calculatecolor(float col)
+{
+ int b;
+
+ if(RG.gamma==1.0) {
+ b= RG.radfactor*col;
+ }
+ else if(RG.gamma==2.0) {
+ b= RG.radfactor*sqrt(col);
+ }
+ else {
+ b= RG.radfactor*pow(col, RG.igamma);
+ }
+
+ if(b>255) b=255;
+ return b;
+}
+
+void make_node_display()
+{
+ RNode *rn, **el;
+ int a;
+ char *charcol;
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+
+ /* gouraudcolor */
+ *(rn->v1+3)= 0;
+ *(rn->v2+3)= 0;
+ *(rn->v3+3)= 0;
+ if(rn->v4) *(rn->v4+3)= 0;
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v1+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v2+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v3+3), 16 );
+ if(rn->v4) addaccuweight( (char *)&(rn->col), (char *)(rn->v4+3), 16 );
+ }
+}
+
+void drawnodeWire(RNode *rn)
+{
+
+ if(rn->down1) {
+ drawnodeWire(rn->down1);
+ drawnodeWire(rn->down2);
+ }
+ else {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawsingnodeWire(RNode *rn)
+{
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+}
+
+void drawnodeSolid(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeSolid(rn->down1);
+ drawnodeSolid(rn->down2);
+ }
+ else {
+ cp= (char *)&rn->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glBegin(GL_POLYGON);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawnodeGour(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeGour(rn->down1);
+ drawnodeGour(rn->down2);
+ }
+ else {
+ glBegin(GL_POLYGON);
+ cp= (char *)(rn->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v1);
+
+ cp= (char *)(rn->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v2);
+
+ cp= (char *)(rn->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v3);
+
+ if(rn->type==4) {
+ cp= (char *)(rn->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v4);
+ }
+ glEnd();
+ }
+}
+
+void drawpatch_ext(RPatch *patch, unsigned int col)
+{
+ ScrArea *sa, *oldsa;
+ View3D *v3d;
+ glDrawBuffer(GL_FRONT);
+
+ return; // XXX
+
+ cpack(col);
+
+ oldsa= NULL; // XXX curarea;
+
+// sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ v3d= sa->spacedata.first;
+
+ /* use mywinget() here: otherwise it draws in header */
+// XXX if(sa->win != mywinget()) areawinset(sa->win);
+// XXX persp(PERSP_VIEW);
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ drawnodeWire(patch->first);
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST); // pretty useless?
+ }
+ sa= sa->next;
+ }
+
+// XXX if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+
+ glFlush();
+ glDrawBuffer(GL_BACK);
+}
+
+
+void drawfaceGour(Face *face)
+{
+ char *cp;
+
+ glBegin(GL_POLYGON);
+ cp= (char *)(face->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v1);
+
+ cp= (char *)(face->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v2);
+
+ cp= (char *)(face->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v3);
+
+ if(face->v4) {
+ cp= (char *)(face->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceSolid(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_POLYGON);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceWire(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawsquare(float *cent, float size, short cox, short coy)
+{
+ float vec[3];
+
+ vec[0]= cent[0];
+ vec[1]= cent[1];
+ vec[2]= cent[2];
+
+ glBegin(GL_LINE_LOOP);
+ vec[cox]+= .5*size;
+ vec[coy]+= .5*size;
+ glVertex3fv(vec);
+ vec[coy]-= size;
+ glVertex3fv(vec);
+ vec[cox]-= size;
+ glVertex3fv(vec);
+ vec[coy]+= size;
+ glVertex3fv(vec);
+ glEnd();
+}
+
+void drawlimits()
+{
+ /* center around cent */
+ short cox=0, coy=1;
+
+ if((RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ))==RAD_SHOWZ) coy= 2;
+ if((RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ))==(RAD_SHOWLIMITS|RAD_SHOWZ)) {
+ cox= 1;
+ coy= 2;
+ }
+
+ cpack(0);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+ cpack(0xFFFFFF);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+ cpack(0xFFFF00);
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+}
+
+void setcolNode(RNode *rn, unsigned int *col)
+{
+
+ if(rn->down1) {
+ setcolNode(rn->down1, col);
+ setcolNode(rn->down2, col);
+ }
+ rn->col= *col;
+
+ *((unsigned int *)rn->v1+3)= *col;
+ *((unsigned int *)rn->v2+3)= *col;
+ *((unsigned int *)rn->v3+3)= *col;
+ if(rn->v4) *((unsigned int *)rn->v4+3)= *col;
+}
+
+void pseudoAmb()
+{
+ RPatch *rp;
+ float fac;
+ char col[4];
+
+ /* sets pseudo ambient color in the nodes */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ col[1]= col[2]= col[3]= 255;
+ }
+ else {
+ fac= rp->norm[0]+ rp->norm[1]+ rp->norm[2];
+ fac= 225.0*(3+fac)/6.0;
+
+ col[3]= fac*rp->ref[0];
+ col[2]= fac*rp->ref[1];
+ col[1]= fac*rp->ref[2];
+ }
+
+ setcolNode(rp->first, (unsigned int *)col);
+
+ rp= rp->next;
+ }
+}
+
+void RAD_drawall(int depth_is_on)
+{
+ /* displays elements or faces */
+ Face *face = NULL;
+ RNode **el;
+ RPatch *rp;
+ int a;
+
+ if(!depth_is_on) {
+ glEnable(GL_DEPTH_TEST);
+ glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ if(RG.totface) {
+ if(RG.drawtype==RAD_GOURAUD) {
+ glShadeModel(GL_SMOOTH);
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceGour(face);
+ }
+ }
+ else if(RG.drawtype==RAD_SOLID) {
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceSolid(face);
+ }
+ }
+ else {
+ cpack(0);
+ rp= RG.patchbase.first;
+ while(rp) {
+ drawsingnodeWire(rp->first);
+ rp= rp->next;
+ }
+ }
+ }
+ else {
+ el= RG.elem;
+ if(RG.drawtype==RAD_GOURAUD) {
+ glShadeModel(GL_SMOOTH);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeGour(*el);
+ }
+ }
+ else if(RG.drawtype==RAD_SOLID) {
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeSolid(*el);
+ }
+ }
+ else {
+ cpack(0);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeWire(*el);
+ }
+ }
+ }
+ glShadeModel(GL_FLAT);
+
+ if(RG.totpatch) {
+ if(RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ)) {
+ if(depth_is_on) glDisable(GL_DEPTH_TEST);
+ drawlimits();
+ if(depth_is_on) glEnable(GL_DEPTH_TEST);
+ }
+ }
+ if(!depth_is_on) {
+ glDisable(GL_DEPTH_TEST);
+ }
+}
+
+void rad_forcedraw()
+{
+ ScrArea *sa, *oldsa;
+
+ return; // XXX
+
+ oldsa= NULL; // XXX curarea;
+
+/// sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ /* use mywinget() here: othwerwise it draws in header */
+// XXX if(sa->win != mywinget()) areawinset(sa->win);
+// XXX scrarea_do_windraw(sa);
+ }
+ sa= sa->next;
+ }
+// XXX screen_swapbuffers();
+
+// XXX if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+}
+
diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c
new file mode 100644
index 00000000000..b87473dd811
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radfactors.c
@@ -0,0 +1,939 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ formfactors.c nov/dec 1992
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "radio.h"
+#include "RE_render_ext.h" /* for `RE_zbufferall_radio and RE_zbufferall_radio */
+
+/* locals */
+static void rad_setmatrices(RadView *vw);
+static void clearsubflagelem(RNode *rn);
+static void setsubflagelem(RNode *rn);
+
+RadView hemitop, hemiside;
+
+float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area)
+{
+ float tvec[3], fac;
+ float vec[4][3]; /* vectors of shoot->cent to vertices rp */
+ float cross[4][3]; /* cross products of this */
+ float rad[4]; /* anlgles between vecs */
+
+ /* test for direction */
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0)
+ return 0.0;
+
+ if(rp->type==4) {
+
+ /* corner vectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+ VecSubf(vec[3], shoot->cent, rn->v4);
+
+ Normalize(vec[0]);
+ Normalize(vec[1]);
+ Normalize(vec[2]);
+ Normalize(vec[3]);
+
+ /* cross product */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[3]);
+ Crossf(cross[3], vec[3], vec[0]);
+ Normalize(cross[0]);
+ Normalize(cross[1]);
+ Normalize(cross[2]);
+ Normalize(cross[3]);
+
+ /* angles */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
+ rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+ rad[3]= acos(rad[3]);
+
+ /* Stoke formula */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+ VecMulf(cross[3], rad[3]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ fac+= tvec[0]*cross[3][0]+ tvec[1]*cross[3][1]+ tvec[2]*cross[3][2];
+ }
+ else {
+ /* corner vectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+
+ Normalize(vec[0]);
+ Normalize(vec[1]);
+ Normalize(vec[2]);
+
+ /* cross product */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[0]);
+ Normalize(cross[0]);
+ Normalize(cross[1]);
+ Normalize(cross[2]);
+
+ /* angles */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[0][0]+ vec[2][1]*vec[0][1]+ vec[2][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+
+ /* Stoke formula */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ }
+
+ *area= -fac/(2.0*PI);
+ return (*area * (shoot->area/rn->area));
+}
+
+
+void calcTopfactors()
+{
+ float xsq , ysq, xysq;
+ float n;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.topfactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ ysq= (n- ((float)a+0.5))/n;
+ ysq*= ysq;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = 1.0/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+void calcSidefactors()
+{
+ float xsq , ysq, xysq;
+ float n, y;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.sidefactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ y= (n- ((float)a+0.5))/n;
+ ysq= y*y;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = y/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+
+void initradiosity()
+{
+ /* allocates and makes LUTs for top/side factors */
+ /* allocates and makes index array */
+ int a, hres2;
+
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ if(RG.index) MEM_freeN(RG.index);
+
+ RG.topfactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity");
+ calcTopfactors();
+ RG.sidefactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity1");
+ calcSidefactors();
+
+ RG.index= MEM_callocN(4*RG.hemires, "initradiosity3");
+ hres2= RG.hemires/2;
+ for(a=0; a<RG.hemires; a++) {
+ RG.index[a]= a<hres2 ? a: (hres2-1-( a % hres2 ));
+ }
+
+}
+
+void rad_make_hocos(RadView *vw)
+{
+ /* float hoco[4]; */
+ /* int a; */
+
+ /* for(a=0; a< R.totvert;a++) { */
+ /* projectvert(vec, ver->ho); */
+ /* ver->clip = testclip(ver->ho); */
+/* */
+ /* } */
+}
+
+static void rad_setmatrices(RadView *vw) /* for hemi's */
+{
+ float up1[3], len, twist;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], 0, vw->viewmat);
+ up1[0] = vw->viewmat[0][0]*vw->up[0] + vw->viewmat[1][0]*vw->up[1] + vw->viewmat[2][0]*vw->up[2];
+ up1[1] = vw->viewmat[0][1]*vw->up[0] + vw->viewmat[1][1]*vw->up[1] + vw->viewmat[2][1]*vw->up[2];
+ up1[2] = vw->viewmat[0][2]*vw->up[0] + vw->viewmat[1][2]*vw->up[1] + vw->viewmat[2][2]*vw->up[2];
+
+ len= up1[0]*up1[0]+up1[1]*up1[1];
+ if(len>0.0) {
+ twist= -atan2(up1[0], up1[1]);
+ }
+ else twist= 0.0;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], (180.0*twist/M_PI), vw->viewmat);
+
+ /* window matrix was set in inithemiwindows */
+
+}
+
+
+void hemizbuf(RadView *vw)
+{
+ float *factors;
+ unsigned int *rz;
+ int a, b, inda, hres;
+
+ rad_setmatrices(vw);
+ RE_zbufferall_radio(vw, RG.elem, RG.totelem, RG.re); /* Render for when we got renderfaces */
+
+ /* count factors */
+ if(vw->recty==vw->rectx) factors= RG.topfactors;
+ else factors= RG.sidefactors;
+ hres= RG.hemires/2;
+
+ rz= vw->rect;
+ for(a=0; a<vw->recty; a++) {
+ inda= hres*RG.index[a];
+ for(b=0; b<vw->rectx; b++, rz++) {
+ if(*rz<RG.totelem) {
+ RG.formfactors[*rz]+= factors[inda+RG.index[b]];
+ }
+ }
+ }
+}
+
+int makeformfactors(RPatch *shoot)
+{
+ RNode **re;
+ float len, vec[3], up[3], side[3], tar[5][3], *fp;
+ int a=0, overfl;
+
+ if(RG.totelem==0) return 0;
+
+ memset(RG.formfactors, 0, 4*RG.totelem);
+
+ /* set up hemiview */
+ /* first: random upvector */
+ do {
+ a++;
+ vec[0]= (float)BLI_drand();
+ vec[1]= (float)BLI_drand();
+ vec[2]= (float)BLI_drand();
+ Crossf(up, shoot->norm, vec);
+ len= Normalize(up);
+ /* this safety for input normals that are zero or illegal sized */
+ if(a>3) return 0;
+ } while(len==0.0 || len>1.0);
+
+ VECCOPY(hemitop.up, up);
+ VECCOPY(hemiside.up, shoot->norm);
+
+ Crossf(side, shoot->norm, up);
+
+ /* five targets */
+ VecAddf(tar[0], shoot->cent, shoot->norm);
+ VecAddf(tar[1], shoot->cent, up);
+ VecSubf(tar[2], shoot->cent, up);
+ VecAddf(tar[3], shoot->cent, side);
+ VecSubf(tar[4], shoot->cent, side);
+
+ /* camera */
+ VECCOPY(hemiside.cam, shoot->cent);
+ VECCOPY(hemitop.cam, shoot->cent);
+
+ /* do it! */
+ VECCOPY(hemitop.tar, tar[0]);
+ hemizbuf(&hemitop);
+
+ for(a=1; a<5; a++) {
+ VECCOPY(hemiside.tar, tar[a]);
+ hemizbuf(&hemiside);
+ }
+
+ /* convert factors to real radiosity */
+ re= RG.elem;
+ fp= RG.formfactors;
+
+ overfl= 0;
+ for(a= RG.totelem; a>0; a--, re++, fp++) {
+
+ if(*fp!=0.0) {
+
+ *fp *= shoot->area/(*re)->area;
+
+ if(*fp>1.0) {
+ overfl= 1;
+ *fp= 1.0001;
+ }
+ }
+ }
+
+ if(overfl) {
+ if(shoot->first->down1) {
+ splitpatch(shoot);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void applyformfactors(RPatch *shoot)
+{
+ RPatch *rp;
+ RNode **el, *rn;
+ float *fp, *ref, unr, ung, unb, r, g, b, w;
+ int a;
+
+ unr= shoot->unshot[0];
+ ung= shoot->unshot[1];
+ unb= shoot->unshot[2];
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++, fp++) {
+ rn= *el;
+ if(*fp!= 0.0) {
+ rp= rn->par;
+ ref= rp->ref;
+
+ r= (*fp)*unr*ref[0];
+ g= (*fp)*ung*ref[1];
+ b= (*fp)*unb*ref[2];
+
+ w= rn->area/rp->area;
+ rn->totrad[0]+= r;
+ rn->totrad[1]+= g;
+ rn->totrad[2]+= b;
+
+ rp->unshot[0]+= w*r;
+ rp->unshot[1]+= w*g;
+ rp->unshot[2]+= w*b;
+ }
+ }
+
+ shoot->unshot[0]= shoot->unshot[1]= shoot->unshot[2]= 0.0;
+}
+
+RPatch *findshootpatch()
+{
+ RPatch *rp, *shoot;
+ float energy, maxenergy;
+
+ shoot= 0;
+ maxenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ energy= rp->unshot[0]*rp->area;
+ energy+= rp->unshot[1]*rp->area;
+ energy+= rp->unshot[2]*rp->area;
+
+ if(energy>maxenergy) {
+ shoot= rp;
+ maxenergy= energy;
+ }
+ rp= rp->next;
+ }
+
+ if(shoot) {
+ maxenergy/= RG.totenergy;
+ if(maxenergy<RG.convergence) return 0;
+ }
+
+ return shoot;
+}
+
+void setnodeflags(RNode *rn, int flag, int set)
+{
+
+ if(rn->down1) {
+ setnodeflags(rn->down1, flag, set);
+ setnodeflags(rn->down2, flag, set);
+ }
+ else {
+ if(set) rn->f |= flag;
+ else rn->f &= ~flag;
+ }
+}
+
+void backface_test(RPatch *shoot)
+{
+ RPatch *rp;
+ float tvec[3];
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp!=shoot) {
+
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*rp->norm[0]+ tvec[1]*rp->norm[1]+ tvec[2]*rp->norm[2]<0.0) {
+ setnodeflags(rp->first, RAD_BACKFACE, 1);
+ }
+ }
+ rp= rp->next;
+ }
+}
+
+void clear_backface_test()
+{
+ RNode **re;
+ int a;
+
+ re= RG.elem;
+ for(a= RG.totelem-1; a>=0; a--, re++) {
+ (*re)->f &= ~RAD_BACKFACE;
+ }
+
+}
+
+void rad_init_energy()
+{
+ /* call before shooting */
+ /* keep patches and elements, clear all data */
+ RNode **el, *rn;
+ RPatch *rp;
+ int a;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, rn->par->emit);
+ }
+
+ RG.totenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ VECCOPY(rp->unshot, rp->emit);
+
+ RG.totenergy+= rp->unshot[0]*rp->area;
+ RG.totenergy+= rp->unshot[1]*rp->area;
+ RG.totenergy+= rp->unshot[2]*rp->area;
+
+ rp->f= 0;
+
+ rp= rp->next;
+ }
+}
+
+void progressiverad()
+{
+ RPatch *shoot;
+ float unshot[3];
+ int it= 0;
+
+ rad_printstatus();
+ rad_init_energy();
+
+ shoot=findshootpatch();
+
+ while( shoot ) {
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ backface_test(shoot);
+
+ drawpatch_ext(shoot, 0x88FF00);
+
+ if(shoot->first->f & RAD_TWOSIDED) {
+ VECCOPY(unshot, shoot->unshot);
+ VecNegf(shoot->norm);
+ if(makeformfactors(shoot))
+ applyformfactors(shoot);
+ VecNegf(shoot->norm);
+ VECCOPY(shoot->unshot, unshot);
+ }
+
+ if( makeformfactors(shoot) ) {
+ applyformfactors(shoot);
+
+ it++;
+ //XXX set_timecursor(it);
+ if( (it & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+
+ clear_backface_test();
+
+ //XXX if(blender_test_break()) break;
+ if(RG.maxiter && RG.maxiter<=it) break;
+
+ shoot=findshootpatch();
+
+ }
+
+}
+
+
+/* ************* subdivideshoot *********** */
+
+void minmaxradelem(RNode *rn, float *min, float *max)
+{
+ int c;
+
+ if(rn->down1) {
+ minmaxradelem(rn->down1, min, max);
+ minmaxradelem(rn->down2, min, max);
+ }
+ else {
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], rn->totrad[c]);
+ max[c]= MAX2(max[c], rn->totrad[c]);
+ }
+ }
+}
+
+void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax)
+{
+ float col[3], area;
+ int c;
+
+ if(rn->down1) {
+ minmaxradelemfilt(rn->down1, min, max, errmin, errmax);
+ minmaxradelemfilt(rn->down2, min, max, errmin, errmax);
+ }
+ else {
+ VECCOPY(col, rn->totrad);
+
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], col[c]);
+ max[c]= MAX2(max[c], col[c]);
+ }
+
+ VecMulf(col, 2.0);
+ area= 2.0;
+ if(rn->ed1) {
+ VecAddf(col, rn->ed1->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ VecAddf(col, rn->ed2->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ VecAddf(col, rn->ed3->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ VecAddf(col, rn->ed4->totrad, col);
+ area+= 1.0;
+ }
+ VecMulf(col, 1.0/area);
+
+ for(c=0; c<3; c++) {
+ errmin[c]= MIN2(errmin[c], col[c]);
+ errmax[c]= MAX2(errmax[c], col[c]);
+ }
+ }
+}
+
+static void setsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f |= RAD_SUBDIV;
+ }
+}
+
+static void clearsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f &= ~RAD_SUBDIV;
+ }
+}
+
+void subdivideshootElements(int it)
+{
+ RPatch *rp, *shoot;
+ RNode **el, *rn;
+ float *fp, err, stoke, area, min[3], max[3], errmin[3], errmax[3];
+ int a, b, c, d, e, f, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ //XXX set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+
+ if( (rn->f & RAD_SUBDIV)==0 && *fp!=0.0) {
+ if(rn->par->emit[0]+rn->par->emit[1]+rn->par->emit[2]==0.0) {
+
+ stoke= calcStokefactor(shoot, rn->par, rn, &area);
+ if(stoke!= 0.0) {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>35.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+ rn->f |= RAD_SUBDIV;
+ rn->par->f |= RAD_SUBDIV;
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ fp++;
+
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+ else a--;
+
+ //XXX if(blender_test_break()) break;
+ }
+
+ /* test for extreme small color change within a patch with subdivflag */
+
+ rp= RG.patchbase.first;
+
+ while(rp) {
+ if(rp->f & RAD_SUBDIV) { /* rp has elems that need subdiv */
+ /* at least 4 levels deep */
+ rn= rp->first->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) rn= rn->down1;
+ }
+ }
+ if(rn) {
+ INIT_MINMAX(min, max);
+ /* errmin and max are the filtered colors */
+ INIT_MINMAX(errmin, errmax);
+ minmaxradelemfilt(rp->first, min, max, errmin, errmax);
+
+ /* if small difference between colors: no subdiv */
+ /* also test for the filtered ones: but with higher critical level */
+
+ contin= 0;
+ a= abs( calculatecolor(min[0])-calculatecolor(max[0]));
+ b= abs( calculatecolor(errmin[0])-calculatecolor(errmax[0]));
+ if(a<15 || b<7) {
+ c= abs( calculatecolor(min[1])-calculatecolor(max[1]));
+ d= abs( calculatecolor(errmin[1])-calculatecolor(errmax[1]));
+ if(c<15 || d<7) {
+ e= abs( calculatecolor(min[2])-calculatecolor(max[2]));
+ f= abs( calculatecolor(errmin[2])-calculatecolor(errmax[2]));
+ if(e<15 || f<7) {
+ contin= 1;
+ clearsubflagelem(rp->first);
+ /* printf("%d %d %d %d %d %d\n", a, b, c, d, e, f); */
+ }
+ }
+ }
+ if(contin) {
+ drawpatch_ext(rp, 0xFFFF);
+ }
+ }
+ }
+ rp->f &= ~RAD_SUBDIV;
+ rp= rp->next;
+ }
+
+ contin= 0;
+
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+ if(rn->f & RAD_SUBDIV) {
+ rn->f-= RAD_SUBDIV;
+ subdivideNode(rn, 0);
+ if(rn->down1) {
+ subdivideNode(rn->down1, 0);
+ subdivideNode(rn->down2, 0);
+ contin= 1;
+ }
+ }
+ }
+ makeGlobalElemArray();
+
+ //XXX if(contin==0 || blender_test_break()) break;
+ }
+
+ make_node_display();
+}
+
+void subdivideshootPatches(int it)
+{
+ RPatch *rp, *shoot, *next;
+ float *fp, err, stoke, area;
+ int a, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ //XXX set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(*fp!=0.0 && rp!=shoot) {
+
+ stoke= calcStokefactor(shoot, rp, rp->first, &area);
+ if(stoke!= 0.0) {
+ if(area>.1) { /* does patch receive more than (about)10% of energy? */
+ rp->f= RAD_SUBDIV;
+ }
+ else {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>45.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+
+ rp->f= RAD_SUBDIV;
+
+ }
+ }
+ }
+ }
+ }
+ }
+ fp++;
+
+ rp= rp->next;
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+
+ //XXX if(blender_test_break()) break;
+ }
+ else a--;
+
+ }
+
+ contin= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->f & RAD_SUBDIV) {
+ if(rp->emit[0]+rp->emit[1]+rp->emit[2]==0.0) {
+ contin= 1;
+ subdivideNode(rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+ }
+ }
+ rp= next;
+ }
+
+ converttopatches();
+ makeGlobalElemArray();
+
+ //XXX if(contin==0 || blender_test_break()) break;
+ }
+ make_node_display();
+}
+
+void inithemiwindows()
+{
+ RadView *vw;
+
+ /* the hemiwindows */
+ vw= &(hemitop);
+ memset(vw, 0, sizeof(RadView));
+ vw->rectx= RG.hemires;
+ vw->recty= RG.hemires;
+ vw->rectz= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows");
+ vw->rect= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows");
+ vw->mynear= RG.maxsize/2000.0;
+ vw->myfar= 2.0*RG.maxsize;
+ vw->wx1= -vw->mynear;
+ vw->wx2= vw->mynear;
+ vw->wy1= -vw->mynear;
+ vw->wy2= vw->mynear;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+ hemiside= hemitop;
+
+ vw= &(hemiside);
+ vw->recty/= 2;
+ vw->wy1= vw->wy2;
+ vw->wy2= 0.0;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+}
+
+void closehemiwindows()
+{
+
+ if(hemiside.rect) MEM_freeN(hemiside.rect);
+ if(hemiside.rectz) MEM_freeN(hemiside.rectz);
+ hemiside.rectz= 0;
+ hemiside.rect= 0;
+ hemitop.rectz= 0;
+ hemitop.rect= 0;
+}
diff --git a/source/blender/radiosity/intern/source/radio.c b/source/blender/radiosity/intern/source/radio.c
new file mode 100644
index 00000000000..63032b2d603
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radio.c
@@ -0,0 +1,390 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ radio.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ - mainloop
+ - interactivity
+
+
+ - PREPROCES
+ - collect meshes
+ - spitconnected (all faces with different color and normals)
+ - setedgepointers (nodes pointing to neighbours)
+
+ - EDITING
+ - min-max patch en min-max element size
+ - using this info patches subdividing
+ - lamp subdivide
+
+ - if there are too many lamps for subdivide shooting:
+ - temporal join patches
+
+ - SUBDIVIDE SHOOTING
+ - except for last shooting, this defines patch subdivide
+ - if subdivided patches still > 2*minsize : continue
+ - at the end create as many elements as possible
+ - als store if lamp (can still) cause subdivide.
+
+ - REFINEMENT SHOOTING
+ - test for overflows (shootpatch subdivide)
+ - testen for extreme color transitions:
+ - if possible: shootpatch subdivide
+ - elements subdivide = start over ?
+ - continue itterate until ?
+
+ - DEFINITIVE SHOOTING
+ - user indicates how many faces maximum and duration of itteration.
+
+ - POST PROCESS
+ - join element- nodes when nothing happens in it (filter nodes, filter faces)
+ - define gamma & mul
+
+ *************************************** */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "radio.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* locals? This one was already done in radio.h... */
+/* void rad_status_str(char *str); */
+
+RadGlobal RG= {0, 0};
+
+void freeAllRad(Scene *scene)
+{
+ Base *base;
+ extern int Ntotvert, Ntotnode, Ntotpatch;
+
+ /* clear flag that disables drawing the meshes */
+ if(scene) {
+ base= (scene->base.first);
+ while(base) {
+ if(base->object->type==OB_MESH) {
+ base->flag &= ~OB_RADIO;
+ }
+ base= base->next;
+ }
+ }
+
+ free_fastAll(); /* verts, nodes, patches */
+ RG.patchbase.first= RG.patchbase.last= 0;
+ Ntotvert= Ntotnode= Ntotpatch= 0;
+
+ closehemiwindows(); /* not real windows anymore... */
+ if(RG.elem) MEM_freeN(RG.elem);
+ RG.elem= 0;
+ if(RG.verts) MEM_freeN(RG.verts);
+ RG.verts= 0;
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ RG.topfactors= 0;
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ RG.sidefactors= 0;
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ RG.formfactors= 0;
+ if(RG.index) MEM_freeN(RG.index);
+ RG.index= 0;
+ if(RG.facebase) {
+ init_face_tab(); /* frees all tables */
+ MEM_freeN(RG.facebase);
+ RG.facebase= 0;
+ }
+
+ if(RG.mfdata) {
+ CustomData_free(RG.mfdata, RG.mfdatatot);
+ MEM_freeN(RG.mfdata);
+ MEM_freeN(RG.mfdatanodes);
+ RG.mfdatanodes= NULL;
+ RG.mfdata= NULL;
+ RG.mfdatatot= 0;
+ }
+ RG.totelem= RG.totpatch= RG.totvert= RG.totface= RG.totlamp= RG.totmat= 0;
+}
+
+int rad_phase()
+{
+ int flag= 0;
+
+ if(RG.totpatch) flag |= RAD_PHASE_PATCHES;
+ if(RG.totface) flag |= RAD_PHASE_FACES;
+
+ return flag;
+}
+
+void rad_status_str(char *str)
+{
+ extern int totfastmem;
+ int tot;
+ char *phase;
+
+ tot= (RG.totface*sizeof(Face))/1024;
+ tot+= totfastmem/1024;
+
+ if(RG.phase==RAD_SHOOTE) phase= "Phase: ELEMENT SUBD, ";
+ else if(RG.phase==RAD_SHOOTP) phase= "Phase: PATCH SUBD, ";
+ else if(RG.phase==RAD_SOLVE) phase= "Phase: SOLVE, ";
+ else if(RG.totpatch==0) phase= "Phase: COLLECT MESHES ";
+ else if(RG.totface) phase= "Phase: FINISHED, ";
+ else phase= "Phase: INIT, ";
+
+ if(RG.totpatch==0) strcpy(str, phase);
+ else sprintf(str, "%s TotPatch: %d TotElem: %d Emit: %d Faces %d Mem: %d k ", phase, RG.totpatch, RG.totelem, RG.totlamp, RG.totface, tot);
+
+ if(RG.phase==RAD_SOLVE) strcat(str, "(press ESC to stop)");
+}
+
+void rad_printstatus()
+{
+ /* actions always are started from a buttonswindow */
+// XX if(curarea) {
+// scrarea_do_windraw(curarea);
+// screen_swapbuffers();
+// }
+}
+
+void rad_setlimits(Scene *scene)
+{
+ Radio *rad= scene->radio;
+ float fac;
+
+ fac= 0.0005*rad->pama;
+ RG.patchmax= RG.maxsize*fac;
+ RG.patchmax*= RG.patchmax;
+ fac= 0.0005*rad->pami;
+ RG.patchmin= RG.maxsize*fac;
+ RG.patchmin*= RG.patchmin;
+
+ fac= 0.0005*rad->elma;
+ RG.elemmax= RG.maxsize*fac;
+ RG.elemmax*= RG.elemmax;
+ fac= 0.0005*rad->elmi;
+ RG.elemmin= RG.maxsize*fac;
+ RG.elemmin*= RG.elemmin;
+}
+
+void set_radglobal(Scene *scene)
+{
+ /* always call before any action is performed */
+ Radio *rad= scene->radio;
+
+ if(RG.radio==0) {
+ /* firsttime and to be sure */
+ memset(&RG, 0, sizeof(RadGlobal));
+ }
+
+ if(rad==0) return;
+
+ if(rad != RG.radio) {
+ if(RG.radio) freeAllRad(scene);
+ memset(&RG, 0, sizeof(RadGlobal));
+ RG.radio= rad;
+ }
+
+ RG.hemires= rad->hemires & 0xFFF0;
+ RG.drawtype= rad->drawtype;
+ RG.flag= rad->flag;
+ RG.subshootp= rad->subshootp;
+ RG.subshoote= rad->subshoote;
+ RG.nodelim= rad->nodelim;
+ RG.maxsublamp= rad->maxsublamp;
+ RG.maxnode= 2*rad->maxnode; /* in button:max elem, subdividing! */
+ RG.convergence= rad->convergence/1000.0;
+ RG.radfac= rad->radfac;
+ RG.gamma= rad->gamma;
+ RG.maxiter= rad->maxiter;
+
+ RG.re= NULL; /* struct render, for when call it from render engine */
+
+ rad_setlimits(scene);
+}
+
+/* called from buttons.c */
+void add_radio(Scene *scene)
+{
+ Radio *rad;
+
+ if(scene->radio) MEM_freeN(scene->radio);
+ rad= scene->radio= MEM_callocN(sizeof(Radio), "radio");
+
+ rad->hemires= 300;
+ rad->convergence= 0.1;
+ rad->radfac= 30.0;
+ rad->gamma= 2.0;
+ rad->drawtype= RAD_SOLID;
+ rad->subshootp= 1;
+ rad->subshoote= 2;
+ rad->maxsublamp= 0;
+
+ rad->pama= 500;
+ rad->pami= 200;
+ rad->elma= 100;
+ rad->elmi= 20;
+ rad->nodelim= 0;
+ rad->maxnode= 10000;
+ rad->maxiter= 120; // arbitrary
+ rad->flag= 2;
+ set_radglobal(scene);
+}
+
+void delete_radio(Scene *scene)
+{
+ freeAllRad(scene);
+ if(scene->radio) MEM_freeN(scene->radio);
+ scene->radio= 0;
+
+ RG.radio= 0;
+}
+
+int rad_go(Scene *scene) /* return 0 when user escapes */
+{
+ double stime= PIL_check_seconds_timer();
+ int retval;
+
+ if(RG.totface) return 0;
+
+ G.afbreek= 0;
+
+ set_radglobal(scene);
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ maxsizePatches();
+
+ setnodelimit(RG.patchmin);
+ RG.phase= RAD_SHOOTP;
+ subdivideshootPatches(RG.subshootp);
+
+ setnodelimit(RG.elemmin);
+ RG.phase= RAD_SHOOTE;
+ subdivideshootElements(RG.subshoote);
+
+ setnodelimit(RG.patchmin);
+ subdividelamps();
+
+ setnodelimit(RG.elemmin);
+
+ RG.phase= RAD_SOLVE;
+ subdiv_elements();
+
+ progressiverad();
+
+ removeEqualNodes(RG.nodelim);
+
+ make_face_tab(); /* now anchored */
+
+ closehemiwindows();
+ RG.phase= 0;
+
+ stime= PIL_check_seconds_timer()-stime;
+ printf("Radiosity solving time: %dms\n", (int) (stime*1000));
+
+ if(G.afbreek==1) retval= 1;
+ else retval= 0;
+
+ G.afbreek= 0;
+
+ return retval;
+}
+
+void rad_subdivshootpatch(Scene *scene)
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal(scene);
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootPatches(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+// XXX allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_subdivshootelem(Scene *scene)
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal(scene);
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootElements(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+// XXX allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_limit_subdivide(Scene *scene)
+{
+
+ if(scene->radio==0) return;
+
+ set_radglobal(scene);
+
+ if(RG.totpatch==0) {
+ /* printf("exit: no relevant data\n"); */
+ return;
+ }
+
+ maxsizePatches();
+
+ init_face_tab(); /* free faces */
+}
diff --git a/source/blender/radiosity/intern/source/radnode.c b/source/blender/radiosity/intern/source/radnode.c
new file mode 100644
index 00000000000..fa23ca5da57
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radnode.c
@@ -0,0 +1,1103 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ node.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ *************************************** */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "radio.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* locals */
+static void *malloc_fast(int size);
+static void *calloc_fast(int size);
+static void free_fast(void *poin, int siz);
+static void deleteTriNodes(RNode *node);
+/* lower because of local type define */
+/* void check_mallocgroup(MallocGroup *mg); */
+
+
+/* ********** fastmalloc ************** */
+
+#define MAL_GROUPSIZE 256
+#define MAL_AVAILABLE 1
+#define MAL_FULL 2
+
+
+
+
+ListBase MallocBase= {0, 0};
+int totfastmem= 0;
+
+typedef struct MallocGroup {
+ struct MallocGroup *next, *prev;
+ short size, flag;
+ short curfree, tot;
+ char flags[MAL_GROUPSIZE];
+ char *data;
+} MallocGroup;
+
+/* one more local */
+void check_mallocgroup(MallocGroup *mg);
+
+void check_mallocgroup(MallocGroup *mg)
+{
+ int a;
+ char *cp;
+
+ if(mg->tot==MAL_GROUPSIZE) {
+ mg->flag= MAL_FULL;
+ return;
+ }
+
+ cp= mg->flags;
+
+ if(mg->curfree<MAL_GROUPSIZE-1) {
+ if(cp[mg->curfree+1]==0) {
+ mg->curfree++;
+ return;
+ }
+ }
+ if(mg->curfree>0) {
+ if(cp[mg->curfree-1]==0) {
+ mg->curfree--;
+ return;
+ }
+ }
+
+ for(a=0; a<MAL_GROUPSIZE; a++) {
+ if(cp[a]==0) {
+ mg->curfree= a;
+ return;
+ }
+ }
+ printf("fastmalloc: shouldnt be here\n");
+}
+
+static void *malloc_fast(int size)
+{
+ MallocGroup *mg;
+ void *retval;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if(mg->flag & MAL_AVAILABLE) {
+ mg->flags[mg->curfree]= 1;
+ mg->tot++;
+ retval= mg->data+mg->curfree*mg->size;
+ check_mallocgroup(mg);
+ return retval;
+ }
+ }
+ mg= mg->prev;
+ }
+
+ /* no free block found */
+ mg= MEM_callocN(sizeof(MallocGroup), "mallocgroup");
+ BLI_addtail(&MallocBase, mg);
+ mg->data= MEM_mallocN(MAL_GROUPSIZE*size, "mallocgroupdata");
+ mg->flag= MAL_AVAILABLE;
+ mg->flags[0]= 1;
+ mg->curfree= 1;
+ mg->size= size;
+ mg->tot= 1;
+
+ totfastmem+= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+
+ return mg->data;
+}
+
+static void *calloc_fast(int size)
+{
+ void *poin;
+
+ poin= malloc_fast(size);
+ memset(poin, 0, size);
+
+ return poin;
+}
+
+static void free_fast(void *poin, int size)
+{
+ MallocGroup *mg;
+ intptr_t val;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if( ((intptr_t)poin) >= ((intptr_t)mg->data) ) {
+ if( ((intptr_t)poin) < ((intptr_t)(mg->data+MAL_GROUPSIZE*size)) ) {
+ val= ((intptr_t)poin) - ((intptr_t)mg->data);
+ val/= size;
+ mg->curfree= val;
+ mg->flags[val]= 0;
+ mg->flag= MAL_AVAILABLE;
+
+ mg->tot--;
+ if(mg->tot==0) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ totfastmem-= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+ }
+ return;
+ }
+ }
+ }
+ mg= mg->prev;
+ }
+ printf("fast free: pointer not in memlist %p size %d\n",
+ poin, size);
+}
+
+/* security: only one function in a time can use it */
+static char *fastmallocstr= 0;
+
+void free_fastAll()
+{
+ MallocGroup *mg;
+
+ mg= MallocBase.first;
+ while(mg) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ mg= MallocBase.first;
+ }
+ totfastmem= 0;
+ fastmallocstr= 0;
+}
+
+void start_fastmalloc(char *str)
+{
+ if(fastmallocstr) {
+// XXX error("Fastmalloc in use: %s", fastmallocstr);
+ return;
+ }
+ fastmallocstr= str;
+}
+
+/* **************************************** */
+
+float nodelimit;
+
+void setnodelimit(float limit)
+{
+ nodelimit= limit;
+
+}
+
+/* ************ memory management *********** */
+
+int Ntotvert=0, Ntotnode=0, Ntotpatch=0;
+
+float *mallocVert()
+{
+ Ntotvert++;
+ return (float *)malloc_fast(16);
+}
+
+float *callocVert()
+{
+ Ntotvert++;
+ return (float *)calloc_fast(16);
+}
+
+void freeVert(float *vert)
+{
+ free_fast(vert, 16);
+ Ntotvert--;
+}
+
+int totalRadVert()
+{
+ return Ntotvert;
+}
+
+RNode *mallocNode()
+{
+ Ntotnode++;
+ return (RNode *)malloc_fast(sizeof(RNode));
+}
+
+RNode *callocNode()
+{
+ Ntotnode++;
+ return (RNode *)calloc_fast(sizeof(RNode));
+}
+
+void freeNode(RNode *node)
+{
+ free_fast(node, sizeof(RNode));
+ Ntotnode--;
+}
+
+void freeNode_recurs(RNode *node)
+{
+
+ if(node->down1) {
+ freeNode_recurs(node->down1);
+ freeNode_recurs(node->down2);
+ }
+
+ node->down1= node->down2= 0;
+ freeNode(node);
+
+}
+
+RPatch *mallocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)malloc_fast(sizeof(RPatch));
+}
+
+RPatch *callocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)calloc_fast(sizeof(RPatch));
+}
+
+void freePatch(RPatch *patch)
+{
+ free_fast(patch, sizeof(RPatch));
+ Ntotpatch--;
+}
+
+/* ************ SUBDIVIDE *********** */
+
+
+void replaceAllNode(RNode *neighb, RNode *newn)
+{
+ /* changes from all neighbours the edgepointers that point to newn->up in new */
+ int ok= 0;
+
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ neighb->ed1= newn;
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ neighb->ed2= newn;
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ neighb->ed3= newn;
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ neighb->ed4= newn;
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceAllNode(neighb->down1, newn);
+ replaceAllNode(neighb->down2, newn);
+ }
+}
+
+void replaceAllNodeInv(RNode *neighb, RNode *old)
+{
+ /* changes from all neighbours the edgepointers that point to old in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->down1) {
+ replaceAllNodeInv(neighb->down1, old);
+ replaceAllNodeInv(neighb->down2, old);
+ }
+}
+
+void replaceAllNodeUp(RNode *neighb, RNode *old)
+{
+ /* changes from all neighbours the edgepointers that point to old in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+ neighb= neighb->up;
+ if(neighb==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->up) {
+ replaceAllNodeUp(neighb, old);
+ }
+}
+
+
+void replaceTestNode(RNode *neighb, RNode **edpp, RNode *newn, int level, float *vert)
+{
+ /* IF neighb->ed points to newn->up
+ * IF edgelevels equal
+ IF testvert is in neighb->ed
+ change pointers both ways
+ ELSE
+ RETURN
+ ELSE
+ IF neighb edgelevel is deeper
+ change neighb pointer
+
+ */
+ int ok= 0;
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ if(neighb->lev1==level) {
+ if(vert==neighb->v1 || vert==neighb->v2) {
+ *edpp= neighb;
+ neighb->ed1= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev1>level) {
+ neighb->ed1= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ if(neighb->lev2==level) {
+ if(vert==neighb->v2 || vert==neighb->v3) {
+ *edpp= neighb;
+ neighb->ed2= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev2>level) {
+ neighb->ed2= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ if(vert==neighb->v3 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ else {
+ if(vert==neighb->v3 || vert==neighb->v4) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ }
+ else if(neighb->lev3>level) {
+ neighb->ed3= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ if(neighb->lev4==level) {
+ if(vert==neighb->v4 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed4= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev4>level) {
+ neighb->ed4= newn;
+ }
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceTestNode(neighb->down1, edpp, newn, level, vert);
+ replaceTestNode(neighb->down2, edpp, newn, level, vert);
+ }
+
+}
+
+int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2)
+{
+ /* compares edgelevels , if equal it sets the vertexpointers */
+
+ if(neighb==0) return 0;
+
+ if(neighb->ed1==node) {
+ if(neighb->lev1==level) {
+ *v1= neighb->v1;
+ *v2= neighb->v2;
+ return 1;
+ }
+ }
+ else if(neighb->ed2==node) {
+ if(neighb->lev2==level) {
+ *v1= neighb->v2;
+ *v2= neighb->v3;
+ return 1;
+ }
+ }
+ else if(neighb->ed3==node) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ *v1= neighb->v3;
+ *v2= neighb->v1;
+ }
+ else {
+ *v1= neighb->v3;
+ *v2= neighb->v4;
+ }
+ return 1;
+ }
+ }
+ else if(neighb->ed4==node) {
+ if(neighb->lev4==level) {
+ *v1= neighb->v4;
+ *v2= neighb->v1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+float edlen(float *v1, float *v2)
+{
+ return (v1[0]-v2[0])*(v1[0]-v2[0])+ (v1[1]-v2[1])*(v1[1]-v2[1])+ (v1[2]-v2[2])*(v1[2]-v2[2]);
+}
+
+
+void subdivideTriNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, fl, *v1, *v2; /* , AreaT3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(node->down1 || node->down2) {
+ /* printf("trinode: subd already done\n"); */
+ return;
+ }
+
+ /* defines subdivide direction */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) return;
+
+ fu= edlen(node->v1, node->v2);
+ fv= edlen(node->v2, node->v3);
+ fl= edlen(node->v3, node->v1);
+
+ if(fu>fv && fu>fl) uvl= 1;
+ else if(fv>fu && fv>fl) uvl= 2;
+ else uvl= 3;
+ }
+ else {
+
+ if(edge==node->ed1) uvl= 1;
+ else if(edge==node->ed2) uvl= 2;
+ else uvl= 3;
+ }
+
+ /* should neighbour nodes be deeper? Recursive! */
+ n1= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ }
+ else if(uvl==2) {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ }
+ else {
+ if(node->ed3 && node->ed3->down1==0) n1= node->ed3;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) { /* also test for ed4 !!! */
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* the subdividing */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 */
+ if(uvl==1) {
+
+ /* FIRST NODE gets edge 2 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+
+ /* SECOND NODE gets edge 3 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev1++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+
+ /* NEW VERTEX from edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==2) {
+
+ /* FIRST NODE gets edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+
+ /* SECOND NODE gets edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+
+ /* NEW VERTEX from edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==3) {
+
+ /* FIRST NODE gets edge 1 */
+ n1->ed2= n2;
+ n1->lev2= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev3++;
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v1);
+
+ /* SECOND NODE gets edge 2 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed2, n2);
+ n2->lev3++;
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v3);
+
+ /* NEW VERTEX from edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v1) {
+ n1->v3= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v1= mallocVert();
+ n1->v3[0]= 0.5*(node->v1[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v1[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v1[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+ }
+ n1->area= AreaT3Dfl(n1->v1, n1->v2, n1->v3);
+ n2->area= AreaT3Dfl(n2->v1, n2->v2, n2->v3);
+
+}
+
+
+void subdivideNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, *v1, *v2;/*, AreaQ3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(Ntotnode>RG.maxnode) return;
+
+ if(node->type==3) {
+ subdivideTriNode(node, edge);
+ return;
+ }
+
+ if(node->down1 || node->down2) {
+ /* printf("subdivide Node: already done \n"); */
+ return;
+ }
+
+ /* defines subdivide direction */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) {
+ return;
+ }
+ fu= fabs(node->v1[0]- node->v2[0])+ fabs(node->v1[1]- node->v2[1]) +fabs(node->v1[2]- node->v2[2]);
+ fv= fabs(node->v1[0]- node->v4[0])+ fabs(node->v1[1]- node->v4[1]) +fabs(node->v1[2]- node->v4[2]);
+ if(fu>fv) uvl= 1;
+ else uvl= 2;
+ }
+ else {
+ if(edge==node->ed1 || edge==node->ed3) uvl= 1;
+ else uvl= 2;
+ }
+
+ /* do neighbour nodes have to be deeper? Recursive! */
+ n1= n2= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ if(node->ed3 && node->ed3->down1==0) n2= node->ed3;
+ }
+ else {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ if(node->ed4 && node->ed4->down1==0) n2= node->ed4;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) {
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+ if(n2) {
+ up= node->up;
+ while(up) {
+ if(n2->ed1==up || n2->ed2==up || n2->ed3==up || n2->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n2, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* the subdividing */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 and 3 */
+ if(uvl==1) {
+
+ /* FIRST NODE gets edge 2 */
+ n1->ed4= n2;
+ n1->lev4= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ n1->lev3++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v3);
+
+ /* SECOND NODE gets edge 4 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed4, n2);
+ n2->lev1++;
+ n2->lev3++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v4);
+
+ /* NEW VERTEX from edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+
+ /* NEW VERTEX from edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v3) {
+ n1->v4= v2;
+ n2->v3= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v3= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v3= mallocVert();
+ n1->v4[0]= 0.5*(node->v3[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v3[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v3[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+ }
+ /* subdivide edge 2 and 4 */
+ else if(uvl==2) {
+
+ /* FIRST NODE gets edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ n1->lev4++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+ replaceTestNode(n1->ed4, &(n1->ed4), n1, n1->lev4, n1->v1);
+
+ /* SECOND NODE gets edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ n2->lev4++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+ replaceTestNode(n2->ed4, &(n2->ed4), n2, n2->lev4, n2->v4);
+
+ /* NEW VERTEX from edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+
+ /* NEW VERTEX from edge 4 */
+ if( setvertexpointersNode(n1->ed4, n1, n1->lev4, &v1, &v2) ) { /* nodes have equal levels */
+ if(v1== n1->v1) {
+ n1->v4= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v1= mallocVert();
+ n1->v4[0]= 0.5*(node->v1[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v1[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v1[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+ }
+
+ n1->area= AreaQ3Dfl(n1->v1, n1->v2, n1->v3, n1->v4);
+ n2->area= AreaQ3Dfl(n2->v1, n2->v2, n2->v3, n2->v4);
+
+}
+
+int comparelevel(RNode *node, RNode *nb, int level)
+{
+ /* recursive descent: test with deepest node */
+ /* return 1 means equal or higher */
+
+ if(nb==0) return 1;
+
+ if(nb->down1) {
+ return 0;
+
+ /* THERE IS AN ERROR HERE, BUT WHAT? (without this function the system
+ works too, but is slower) (ton) */
+
+ /*
+ n1= nb->down1;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ n1= nb->down2;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ printf(" dit kan niet ");
+ return 0;
+ */
+
+ }
+
+ if(nb->down1==0) {
+ /* if(nb->ed1==node) return (nb->lev1<=level); */
+ /* if(nb->ed2==node) return (nb->lev2<=level); */
+ /* if(nb->ed3==node) return (nb->lev3<=level); */
+ /* if(nb->ed4==node) return (nb->lev4<=level); */
+
+ return 1; /* is higher node */
+ }
+ return 1;
+}
+
+static void deleteTriNodes(RNode *node) /* both children of node */
+{
+ RNode *n1, *n2;
+
+ /* if neighbour nodes are deeper: no delete */
+ /* just test 2 nodes, from the others the level doesn't change */
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ /* at the edges no subdivided node is allowed */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+
+ n1->down1= (RNode *)12; /* for debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+}
+
+ /* both children of node */
+void deleteNodes(RNode *node)
+{
+ RNode *n1, *n2;
+
+ /* if neighbour nodes are deeper: no delete */
+ /* just test 2 nodes, from the others the level doesn't change */
+
+ if(node->type==3) {
+ deleteTriNodes(node);
+ return;
+ }
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ if(n1->ed3==n2) {
+
+ /* at the edges no subdivided node is allowed */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed4 && n1->ed4->down1) return;
+
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed4, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed4, n1);
+
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* for debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+ else if(n1->ed4==n2) {
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* for debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+
+}
+
+
diff --git a/source/blender/radiosity/intern/source/radpostprocess.c b/source/blender/radiosity/intern/source/radpostprocess.c
new file mode 100644
index 00000000000..6912c737a51
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpostprocess.c
@@ -0,0 +1,824 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ radpostprocess.c nov/dec 1992
+ may 1999
+
+ - faces
+ - filtering and node-limit
+ - apply to meshes
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_ghash.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "radio.h"
+
+/* locals? not. done in radio.h... */
+/* void rad_addmesh(void); */
+/* void rad_replacemesh(void); */
+
+void addaccu(register char *z, register char *t)
+{
+ register int div, mul;
+
+ mul= *t;
+ div= mul+1;
+ (*t)++;
+
+ t[1]= (mul*t[1]+z[1])/div;
+ t[2]= (mul*t[2]+z[2])/div;
+ t[3]= (mul*t[3]+z[3])/div;
+
+}
+
+void addaccuweight(register char *z, register char *t, int w)
+{
+ register int div, mul;
+
+ if(w==0) w= 1;
+
+ mul= *t;
+ div= mul+w;
+ if(div>255) return;
+ (*t)= div;
+
+ t[1]= (mul*t[1]+w*z[1])/div;
+ t[2]= (mul*t[2]+w*z[2])/div;
+ t[3]= (mul*t[3]+w*z[3])/div;
+
+}
+
+void triaweight(Face *face, int *w1, int *w2, int *w3)
+{
+ float n1[3], n2[3], n3[3], temp;
+
+ n1[0]= face->v2[0]-face->v1[0];
+ n1[1]= face->v2[1]-face->v1[1];
+ n1[2]= face->v2[2]-face->v1[2];
+ n2[0]= face->v3[0]-face->v2[0];
+ n2[1]= face->v3[1]-face->v2[1];
+ n2[2]= face->v3[2]-face->v2[2];
+ n3[0]= face->v1[0]-face->v3[0];
+ n3[1]= face->v1[1]-face->v3[1];
+ n3[2]= face->v1[2]-face->v3[2];
+ Normalize(n1);
+ Normalize(n2);
+ Normalize(n3);
+ temp= 32.0/(PI);
+ *w1= 0.5+temp*acos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
+ *w2= 0.5+temp*acos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ *w3= 0.5+temp*acos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+
+}
+
+
+
+void init_face_tab()
+{
+ int a= 0;
+
+ if(RG.facebase==0) {
+ RG.facebase= MEM_callocN(sizeof(void *)*RAD_MAXFACETAB, "init_face_tab");
+ }
+ for(a=0; a<RAD_MAXFACETAB; a++) {
+ if(RG.facebase[a]==0) break;
+ MEM_freeN(RG.facebase[a]);
+ RG.facebase[a]= 0;
+ }
+ RG.totface= 0;
+}
+
+Face *addface()
+{
+ Face *face;
+ int a;
+
+ if(RG.totface<0 || RG.totface>RAD_MAXFACETAB*1024 ) {
+ printf("error in addface: %d\n", RG.totface);
+ return 0;
+ }
+ a= RG.totface>>10;
+ face= RG.facebase[a];
+ if(face==0) {
+ face= MEM_callocN(1024*sizeof(Face),"addface");
+ RG.facebase[a]= face;
+ }
+ face+= (RG.totface & 1023);
+
+ RG.totface++;
+
+ return face;
+
+}
+
+Face * makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn)
+{
+ Face *face;
+
+ face= addface();
+ face->v1= v1;
+ face->v2= v2;
+ face->v3= v3;
+ face->v4= v4;
+ face->col= rn->col;
+ face->matindex= rn->par->matindex;
+ face->orig= rn->orig;
+
+ return face;
+}
+
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag)
+{
+ Face *face;
+
+ switch(flag) {
+ case 1:
+ face = makeface(rn->v1, v1, rn->v4, NULL, rn);
+ face = makeface(v1, rn->v3, rn->v4, NULL, rn);
+ face = makeface(v1, rn->v2, rn->v3, NULL, rn);
+ break;
+ case 2:
+ face = makeface(rn->v2, v2, rn->v1, NULL, rn);
+ face = makeface(v2, rn->v4, rn->v1, NULL, rn);
+ face = makeface(v2, rn->v3, rn->v4, NULL, rn);
+ break;
+ case 4:
+ face = makeface(rn->v3, v3, rn->v2, NULL, rn);
+ face = makeface(v3, rn->v1, rn->v2, NULL, rn);
+ face = makeface(v3, rn->v4, rn->v1, NULL, rn);
+ break;
+ case 8:
+ face = makeface(rn->v4, v4, rn->v3, NULL, rn);
+ face = makeface(v4, rn->v2, rn->v3, NULL, rn);
+ face = makeface(v4, rn->v1, rn->v2, NULL, rn);
+ break;
+ case 3:
+ face = makeface(rn->v1, v1, rn->v4, NULL, rn);
+ face = makeface(v1, v2, rn->v4, NULL, rn);
+ face = makeface(v1, rn->v2, v2, NULL, rn);
+ face = makeface(v2, rn->v3, rn->v4, NULL, rn);
+ break;
+ case 6:
+ face = makeface(rn->v2, v2, rn->v1, NULL, rn);
+ face = makeface(v2, v3, rn->v1, NULL, rn);
+ face = makeface(v2, rn->v3, v3, NULL, rn);
+ face = makeface(v3, rn->v4, rn->v1, NULL, rn);
+ break;
+ case 12:
+ face = makeface(rn->v3, v3, rn->v2, NULL, rn);
+ face = makeface(v3, v4, rn->v2, NULL, rn);
+ face = makeface(v3, rn->v4, v4, NULL, rn);
+ face = makeface(v4, rn->v1, rn->v2, NULL, rn);
+ break;
+ case 9:
+ face = makeface(rn->v4, v4, rn->v3, NULL, rn);
+ face = makeface(v4, v1, rn->v3, NULL, rn);
+ face = makeface(v4, rn->v1, v1, NULL, rn);
+ face = makeface(v1, rn->v2, rn->v3, NULL, rn);
+ break;
+ case 5:
+ face = makeface(rn->v1, v1, v3, rn->v4, rn);
+ face = makeface(v1, rn->v2, rn->v3, v3, rn);
+ break;
+ case 10:
+ face = makeface(rn->v1, rn->v2, v2, v4, rn);
+ face = makeface(v4, v2, rn->v3, rn->v4, rn);
+ break;
+ case 7:
+ face = makeface(rn->v1, v1, v3, rn->v4, rn);
+ face = makeface(v1, v2, v3, NULL, rn);
+ face = makeface(v1, rn->v2, v2, NULL, rn);
+ face = makeface(v2, rn->v3, v3, NULL, rn);
+ break;
+ case 14:
+ face = makeface(rn->v2, v2, v4, rn->v1, rn);
+ face = makeface(v2, v3, v4, NULL, rn);
+ face = makeface(v2, rn->v3, v3, NULL, rn);
+ face = makeface(v3, rn->v4, v4, NULL, rn);
+ break;
+ case 13:
+ face = makeface(rn->v3, v3, v1, rn->v2, rn);
+ face = makeface(v3, v4, v1, NULL, rn);
+ face = makeface(v3, rn->v4, v4, NULL, rn);
+ face = makeface(v4, rn->v1, v1, NULL, rn);
+ break;
+ case 11:
+ face = makeface(rn->v4, v4, v2, rn->v3, rn);
+ face = makeface(v4, v1, v2, NULL, rn);
+ face = makeface(v4, rn->v1, v1, NULL, rn);
+ face = makeface(v1, rn->v2, v2, NULL, rn);
+ break;
+ case 15:
+ face = makeface(v1, v2, v3, v4, rn);
+ face = makeface(v1, rn->v2, v2, NULL, rn);
+ face = makeface(v2, rn->v3, v3, NULL, rn);
+ face = makeface(v3, rn->v4, v4, NULL, rn);
+ face = makeface(v4, rn->v1, v1, NULL, rn);
+ break;
+ }
+}
+
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag)
+{
+ Face *face;
+
+ switch(flag) {
+ case 1:
+ face = makeface(rn->v1, v1, rn->v3, NULL, rn);
+ face = makeface(v1, rn->v2, rn->v3, NULL, rn);
+ break;
+ case 2:
+ face = makeface(rn->v2, v2, rn->v1, NULL, rn);
+ face = makeface(v2, rn->v3, rn->v1, NULL, rn);
+ break;
+ case 4:
+ face = makeface(rn->v3, v3, rn->v2, NULL, rn);
+ face = makeface(v3, rn->v1, rn->v2, NULL, rn);
+ break;
+ case 3:
+ face = makeface(rn->v1, v2, rn->v3, NULL, rn);
+ face = makeface(rn->v1, v1, v2, NULL, rn);
+ face = makeface(v1, rn->v2, v2, NULL, rn);
+ break;
+ case 6:
+ face = makeface(rn->v2, v3, rn->v1, NULL, rn);
+ face = makeface(rn->v2, v2, v3, NULL, rn);
+ face = makeface(v2, rn->v3, v3, NULL, rn);
+ break;
+ case 5:
+ face = makeface(rn->v3, v1, rn->v2, NULL, rn);
+ face = makeface(rn->v3, v3, v1, NULL, rn);
+ face = makeface(v3, rn->v1, v1, NULL, rn);
+ break;
+
+ case 7:
+ face = makeface(v1, v2, v3, NULL, rn);
+ face = makeface(rn->v1, v1, v3, NULL, rn);
+ face = makeface(rn->v2, v2, v1, NULL, rn);
+ face = makeface(rn->v3, v3, v2, NULL, rn);
+ break;
+ }
+}
+
+
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2)
+{
+ int test= 0;
+
+ if(nb==0) return 0;
+
+ if(nb->ed1==node) {
+ if(nb->v1==v1 || nb->v1==v2) test++;
+ if(nb->v2==v1 || nb->v2==v2) test+=2;
+ if(test==1) return nb->v2;
+ else if(test==2) return nb->v1;
+ }
+ else if(nb->ed2==node) {
+ if(nb->v2==v1 || nb->v2==v2) test++;
+ if(nb->v3==v1 || nb->v3==v2) test+=2;
+ if(test==1) return nb->v3;
+ else if(test==2) return nb->v2;
+ }
+ else if(nb->ed3==node) {
+ if(nb->type==4) {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v4==v1 || nb->v4==v2) test+=2;
+ if(test==1) return nb->v4;
+ else if(test==2) return nb->v3;
+ }
+ else {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v3;
+ }
+ }
+ else if(nb->ed4==node) {
+ if(nb->v4==v1 || nb->v4==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v4;
+ }
+ return 0;
+}
+
+void make_face_tab() /* takes care of anchoring */
+{
+ RNode *rn, **el;
+ Face *face = NULL;
+ float *v1, *v2, *v3, *v4;
+ int a, flag, w1, w2, w3;
+ char *charcol;
+
+ if(RG.totelem==0) return;
+
+ init_face_tab();
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ /* convert face colors */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+ }
+
+ /* check nodes and make faces */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+
+ rn= *el;
+
+ rn->v1[3]= 0.0;
+ rn->v2[3]= 0.0;
+ rn->v3[3]= 0.0;
+ if(rn->v4) rn->v4[3]= 0.0;
+
+ /* test edges for subdivide */
+ flag= 0;
+ v1= v2= v3= v4= 0;
+ if(rn->ed1) {
+ v1= findmiddlevertex(rn, rn->ed1->down1, rn->v1, rn->v2);
+ if(v1) flag |= 1;
+ }
+ if(rn->ed2) {
+ v2= findmiddlevertex(rn, rn->ed2->down1, rn->v2, rn->v3);
+ if(v2) flag |= 2;
+ }
+ if(rn->ed3) {
+ if(rn->type==4)
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v4);
+ else
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v1);
+ if(v3) flag |= 4;
+ }
+ if(rn->ed4) {
+ v4= findmiddlevertex(rn, rn->ed4->down1, rn->v4, rn->v1);
+ if(v4) flag |= 8;
+ }
+
+ /* using flag and vertexpointers now Faces can be made */
+
+ if(flag==0) {
+ makeface(rn->v1, rn->v2, rn->v3, rn->v4, rn);
+ }
+ else if(rn->type==4) anchorQuadface(rn, v1, v2, v3, v4, flag);
+ else anchorTriface(rn, v1, v2, v3, flag);
+ }
+
+ /* add */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+
+}
+
+void filterFaces()
+{
+ /* put vertex colors in faces, and put them back */
+
+ Face *face = NULL;
+ int a, w1, w2, w3;
+
+ if(RG.totface==0) return;
+
+ /* clear */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->col= 0;
+ }
+
+ /* add: vertices with faces */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v4+3), (char *)&(face->col), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), w1 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), w2 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), w3 );
+ }
+ }
+
+ /* clear */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->v1[3]= 0.0;
+ face->v2[3]= 0.0;
+ face->v3[3]= 0.0;
+ if(face->v4) face->v4[3]= 0.0;
+ }
+
+
+ /* add: faces with vertices */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+}
+
+void calcfiltrad(RNode *rn, float *cd)
+{
+ float area;
+
+ cd[0]= 2.0*rn->totrad[0];
+ cd[1]= 2.0*rn->totrad[1];
+ cd[2]= 2.0*rn->totrad[2];
+ area= 2.0;
+
+ if(rn->ed1) {
+ cd[0]+= rn->ed1->totrad[0];
+ cd[1]+= rn->ed1->totrad[1];
+ cd[2]+= rn->ed1->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ cd[0]+= rn->ed2->totrad[0];
+ cd[1]+= rn->ed2->totrad[1];
+ cd[2]+= rn->ed2->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ cd[0]+= rn->ed3->totrad[0];
+ cd[1]+= rn->ed3->totrad[1];
+ cd[2]+= rn->ed3->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ cd[0]+= rn->ed4->totrad[0];
+ cd[1]+= rn->ed4->totrad[1];
+ cd[2]+= rn->ed4->totrad[2];
+ area+= 1.0;
+ }
+ cd[0]/= area;
+ cd[1]/= area;
+ cd[2]/= area;
+
+}
+
+void filterNodes()
+{
+ /* colors from nodes in tempblock and back */
+
+ RNode *rn, **el;
+ float *coldata, *cd;
+ int a;
+
+ if(RG.totelem==0) return;
+ /* the up-nodes need a color */
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]= 0.0;
+ rn->up->totrad[1]= 0.0;
+ rn->up->totrad[2]= 0.0;
+ if(rn->up->up) {
+ rn->up->up->totrad[0]= 0.0;
+ rn->up->up->totrad[1]= 0.0;
+ rn->up->up->totrad[2]= 0.0;
+ }
+ }
+ }
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]+= 0.5*rn->totrad[0];
+ rn->up->totrad[1]+= 0.5*rn->totrad[1];
+ rn->up->totrad[2]+= 0.5*rn->totrad[2];
+ if(rn->up->up) {
+ rn->up->up->totrad[0]+= 0.25*rn->totrad[0];
+ rn->up->up->totrad[1]+= 0.25*rn->totrad[1];
+ rn->up->up->totrad[2]+= 0.25*rn->totrad[2];
+ }
+ }
+ }
+
+ /* add using area */
+ cd= coldata= MEM_mallocN(3*4*RG.totelem, "filterNodes");
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ calcfiltrad(*el, cd);
+ cd+= 3;
+ }
+
+ cd= coldata;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, cd);
+ cd+= 3;
+ }
+ MEM_freeN(coldata);
+}
+
+void removeEqualNodes(short limit)
+{
+ /* nodes with equal colors: remove */
+ RNode **el, *rn, *rn1;
+ float thresh, f1, f2;
+ int a, foundone=1, ok;
+ int c1, c2;
+
+ if(limit==0) return;
+
+ thresh= 1.0/(256.0*RG.radfactor);
+ thresh= 3.0*pow(thresh, RG.gamma);
+
+// XXX waitcursor(1);
+
+ while(foundone) {
+ foundone= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>1; a--, el++) {
+ rn= *el;
+ rn1= *(el+1);
+
+ if(rn!=rn->par->first && rn1!=rn1->par->first) {
+ if(rn->up && rn->up==rn1->up) {
+ f1= rn->totrad[0]+ rn->totrad[1]+ rn->totrad[2];
+ f2= rn1->totrad[0]+ rn1->totrad[1]+ rn1->totrad[2];
+
+ ok= 0;
+ if(f1<thresh && f2<thresh) ok= 1;
+ else {
+ c1= calculatecolor(rn->totrad[0]);
+ c2= calculatecolor(rn1->totrad[0]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[1]);
+ c2= calculatecolor(rn1->totrad[1]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[2]);
+ c2= calculatecolor(rn1->totrad[2]);
+
+ if( abs(c1-c2)<=limit ) {
+ ok= 1;
+ }
+ }
+ }
+ }
+
+ if(ok) {
+ rn->up->totrad[0]= 0.5f*(rn->totrad[0]+rn1->totrad[0]);
+ rn->up->totrad[1]= 0.5f*(rn->totrad[1]+rn1->totrad[1]);
+ rn->up->totrad[2]= 0.5f*(rn->totrad[2]+rn1->totrad[2]);
+ rn1= rn->up;
+ deleteNodes(rn1);
+ if(rn1->down1) ;
+ else {
+ foundone++;
+ a--; el++;
+ }
+ }
+ }
+ }
+ }
+ if(foundone) {
+ makeGlobalElemArray();
+ }
+ }
+// XXX waitcursor(0);
+}
+
+unsigned int rad_find_or_add_mvert(Mesh *me, MFace *mf, RNode *orignode, float *w, float *radco, GHash *hash)
+{
+ MVert *mvert = BLI_ghash_lookup(hash, radco);
+
+ if(!mvert) {
+ mvert = &me->mvert[me->totvert];
+ VECCOPY(mvert->co, radco);
+ me->totvert++;
+
+ BLI_ghash_insert(hash, radco, mvert);
+ }
+
+ InterpWeightsQ3Dfl(orignode->v1, orignode->v2, orignode->v3,
+ orignode->v4, mvert->co, w);
+
+ return (unsigned int)(mvert - me->mvert);
+}
+
+void rad_addmesh(Scene *scene)
+{
+ Face *face = NULL;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mf;
+ RNode *node;
+ Material *ma=0;
+ GHash *verthash;
+ unsigned int *mcol;
+ float cent[3], min[3], max[3], w[4][4];
+ int a;
+
+ if(RG.totface==0)
+ return;
+
+// if(RG.totmat==MAXMAT)
+// XXX notice("warning: cannot assign more than 16 materials to 1 mesh");
+
+ /* create the mesh */
+ ob= add_object(scene, OB_MESH);
+
+ me= ob->data;
+ me->totvert= totalRadVert();
+ me->totface= RG.totface;
+ me->flag= 0;
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
+ CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
+ CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
+
+ CustomData_merge(RG.mfdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
+ mesh_update_customdata_pointers(me);
+
+ /* create materials and set vertex color flag */
+ for(a=0; a<RG.totmat; a++) {
+ assign_material(ob, RG.matar[a], a+1);
+ ma= RG.matar[a];
+ if(ma) ma->mode |= MA_VERTEXCOL;
+ }
+
+ /* create vertices and faces in one go, adding vertices to the end of the
+ mvert array if they were not added already */
+ me->totvert= 0;
+ verthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ mcol= (unsigned int*)me->mcol;
+ mf= me->mface;
+
+ for(a=0; a<me->totface; a++, mf++, mcol+=4) {
+ RAD_NEXTFACE(a);
+
+ /* the original node that this node is a subnode of */
+ node= RG.mfdatanodes[face->orig];
+
+ /* set mverts from the radio data, and compute interpolation weights */
+ mf->v1= rad_find_or_add_mvert(me, mf, node, w[0], face->v1, verthash);
+ mf->v2= rad_find_or_add_mvert(me, mf, node, w[1], face->v2, verthash);
+ mf->v3= rad_find_or_add_mvert(me, mf, node, w[2], face->v3, verthash);
+ if(face->v4)
+ mf->v4= rad_find_or_add_mvert(me, mf, node, w[3], face->v4, verthash);
+
+ /* copy face and interpolate data */
+ mf->mat_nr= face->matindex;
+
+ CustomData_copy_data(RG.mfdata, &me->fdata, face->orig, a, 1);
+ CustomData_interp(RG.mfdata, &me->fdata, &face->orig, NULL, (float*)w, 1, a);
+
+ /* load face vertex colors, with alpha added */
+ mcol[0]= *((unsigned int*)face->v1+3) | 0x1000000;
+ mcol[1]= *((unsigned int*)face->v2+3) | 0x1000000;
+ mcol[2]= *((unsigned int*)face->v3+3) | 0x1000000;
+ if(face->v4)
+ mcol[3]= *((unsigned int*)face->v4+3) | 0x1000000;
+
+ /* reorder face indices if needed to make face->v4 == 0 */
+ test_index_face(mf, &me->fdata, a, face->v4? 4: 3);
+ }
+
+ BLI_ghash_free(verthash, NULL, NULL);
+
+ /* boundbox and center new */
+ INIT_MINMAX(min, max);
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+
+ VECCOPY(ob->loc, cent);
+
+ /* create edges */
+ make_edges(me, 0);
+}
+
+void rad_replacemesh(Scene *scene)
+{
+ RPatch *rp;
+
+// XXX deselectall();
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if( exist_object(rp->from)) {
+ if (rp->from->type == OB_MESH) {
+ rp->from->flag |= SELECT;
+ }
+ }
+ rp= rp->next;
+ }
+
+ copy_objectflags(scene);
+// XXX delete_obj(1);
+
+ rad_addmesh(scene);
+}
+
diff --git a/source/blender/radiosity/intern/source/radpreprocess.c b/source/blender/radiosity/intern/source/radpreprocess.c
new file mode 100644
index 00000000000..2b3ce1a856b
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpreprocess.c
@@ -0,0 +1,828 @@
+ /* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+
+
+
+ preproces.c nov/dec 1992
+ may 1999
+
+ - collect from meshes
+ - countglobaldata()
+ - makeGlobalElemArray()
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h" /* during_script() */
+#include "BKE_utildefines.h"
+
+#include "radio.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+void setparelem(RNode *rn, RPatch *par);
+
+void splitconnected()
+{
+ /* Since input meshes can have faces with sharing vertices, the geometry is being tested here.
+ * Using normals and colors, faces are split separately. we do this by storing for each
+ * vertex a normal and a color
+ */
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, *next, *vnc1;
+ int a;
+
+ /* test if we need a split */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ if((rp->f1 & RAD_NO_SPLIT)==0) {
+ for(a=0; a<rp->type; a++) {
+
+ if(a==0) vnc= (VeNoCo *)rn->v1;
+ else if(a==1) vnc= (VeNoCo *)rn->v2;
+ else if(a==2) vnc= (VeNoCo *)rn->v3;
+ else vnc= (VeNoCo *)rn->v4;
+
+ if(vnc->flag==0) {
+ vnc->n= (float *)rp->norm;
+ vnc->col= (float *)rp->ref;
+ vnc->flag= 1;
+ }
+ else { /* is face from this vertex allowed for gouraud? */
+ vnc1= vnc;
+ while(vnc1) {
+ if(VecCompare(vnc1->n, rp->norm, 0.01f)) {
+ if(VecCompare(vnc1->col, rp->ref, 0.01f)) {
+ break;
+ }
+ }
+ vnc= vnc1;
+ vnc1= vnc1->next;
+ }
+ if(vnc1==0) {
+ vnc1= MEM_mallocN(sizeof(VeNoCo), "splitconn");
+ vnc1->next= 0;
+ vnc1->v= mallocVert();
+ vnc->next= vnc1;
+ VECCOPY(vnc1->v, vnc->v);
+ vnc1->n= (float *)rp->norm;
+ vnc1->col= (float *)rp->ref;
+ }
+ if(a==0) rn->v1= (float *)vnc1;
+ else if(a==1) rn->v2= (float *)vnc1;
+ else if(a==2) rn->v3= (float *)vnc1;
+ else rn->v4= (float *)vnc1;
+ }
+ }
+ }
+ rp= rp->next;
+ }
+ /* adapt vertexpointers from nodes */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ rn->v1= ((VeNoCo *)(rn->v1))->v;
+ rn->v2= ((VeNoCo *)(rn->v2))->v;
+ rn->v3= ((VeNoCo *)(rn->v3))->v;
+ if(rp->type==4) rn->v4= ((VeNoCo *)(rn->v4))->v;
+
+ rp= rp->next;
+ }
+
+
+ /* free all */
+ vnc= RG.verts;
+ for(a=0; a<RG.totvert; a++) {
+ vnc1= vnc->next;
+ while(vnc1) {
+ next= vnc1->next;
+ MEM_freeN(vnc1);
+ vnc1= next;
+ }
+ vnc++;
+ }
+ MEM_freeN(RG.verts);
+ RG.verts= 0;
+}
+
+int vergedge(const void *v1,const void *v2)
+{
+ int *e1, *e2;
+
+ e1= (int *)v1;
+ e2= (int *)v2;
+
+ if( e1[0] > e2[0] ) return 1;
+ else if( e1[0] < e2[0] ) return -1;
+ else if( e1[1] > e2[1] ) return 1;
+ else if( e1[1] < e2[1] ) return -1;
+
+ return 0;
+}
+
+
+void addedge(float *v1, float *v2, EdSort *es)
+{
+ if( ((intptr_t)v1)<((intptr_t)v2) ) {
+ es->v1= v1;
+ es->v2= v2;
+ }
+ else {
+ es->v2= v1;
+ es->v1= v2;
+ }
+}
+
+static void setedge(RNode *node, RNode *nb, int nr, int nrb)
+{
+ switch(nr) {
+ case 1:
+ node->ed1= nb;
+ break;
+ case 2:
+ node->ed2= nb;
+ break;
+ case 3:
+ node->ed3= nb;
+ break;
+ case 4:
+ node->ed4= nb;
+ break;
+ }
+ switch(nrb) {
+ case 1:
+ nb->ed1= node;
+ break;
+ case 2:
+ nb->ed2= node;
+ break;
+ case 3:
+ nb->ed3= node;
+ break;
+ case 4:
+ nb->ed4= node;
+ break;
+ }
+}
+
+void setedgepointers()
+{
+ /* make edge-array and sort it */
+ /* pairs of edges are put together: fill in pointers in nodes */
+ EdSort *es, *esblock;
+ RPatch *rp;
+ RNode *rn;
+ int tot= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ tot+= rp->type;
+ rp= rp->next;
+ }
+
+ if(tot==0) return;
+
+ es=esblock= MEM_mallocN(tot*sizeof(EdSort), "setedgepointers");
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ addedge(rn->v1, rn->v2, es);
+ es->nr= 1;
+ es->node= rn;
+ es++;
+ addedge(rn->v2, rn->v3, es);
+ es->nr= 2;
+ es->node= rn;
+ es++;
+ if(rp->type==3) {
+ addedge(rn->v3, rn->v1, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ }
+ else {
+ addedge(rn->v3, rn->v4, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ addedge(rn->v4, rn->v1, es);
+ es->nr= 4;
+ es->node= rn;
+ es++;
+ }
+ rp= rp->next;
+ }
+
+ qsort(esblock,tot,sizeof(EdSort),vergedge);
+
+ es= esblock;
+ while(tot>0) {
+ if( es->v1== (es+1)->v1 ) {
+ if( es->v2== (es+1)->v2 ) {
+ setedge(es->node, (es+1)->node, es->nr, (es+1)->nr);
+ tot--;
+ es++;
+ }
+ }
+ es++;
+ tot--;
+ }
+
+ MEM_freeN(esblock);
+}
+
+static int materialIndex(Material *ma)
+{
+ int i = 0;
+ for(i=0;i< RG.totmat; i++)
+ {
+ if (RG.matar[i] == ma) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void rad_collect_meshes(Scene *scene, View3D *v3d)
+{
+ extern Material defmaterial;
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ MTFace *tf, *tface;
+ Material *ma = NULL, *noma= NULL;
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, **nodevert;
+ float *vd, *v1, *v2, *v3, *v4 = NULL;
+ int a, b, offs, index, mfdatatot;
+
+ if (v3d==NULL) {
+ printf("Error, trying to collect radiosity meshes with no 3d view\n");
+ return;
+ }
+
+ set_radglobal(scene);
+
+ freeAllRad(scene);
+
+ start_fastmalloc("Radiosity");
+
+ /* count the number of verts */
+ RG.totvert= 0;
+ RG.totface= 0;
+ base= (scene->base.first);
+ while(base) {
+ if(((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
+ if(base->object->type==OB_MESH) {
+ base->flag |= OB_RADIO;
+ me= base->object->data;
+ RG.totvert+= me->totvert;
+ }
+ }
+ base= base->next;
+ }
+ if(RG.totvert==0) {
+ if (!during_script()); //XXX error("No vertices");
+ return;
+ }
+ vnc= RG.verts= MEM_callocN(RG.totvert*sizeof(VeNoCo), "radioverts");
+
+ RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20f;
+ RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20f;
+
+ mfdatatot= 0;
+
+ /* min-max and material array */
+ base= (scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ vd= mallocVert();
+ VECCOPY(vd, mvert->co);
+ /* Should make MTC its own module... */
+ Mat4MulVecfl(base->object->obmat, vd);
+
+ vnc->v= vd;
+ for(b=0; b<3; b++) {
+ RG.min[b]= MIN2(RG.min[b], vd[b]);
+ RG.max[b]= MAX2(RG.max[b], vd[b]);
+ }
+ vnc++;
+ }
+
+ if(base->object->totcol==0) {
+ if(RG.totmat<MAXMAT) {
+ if(noma==NULL) {
+ noma= add_material("RadioMat");
+ RG.matar[RG.totmat]= noma;
+ RG.totmat++;
+ }
+ }
+ }
+ else {
+ for(a=0; a<base->object->totcol; a++) {
+ if(RG.totmat >= MAXMAT) break;
+
+ ma = give_current_material(base->object, a+1);
+
+ if (materialIndex(ma)!=-1) break;
+
+ RG.matar[RG.totmat]= ma;
+ RG.totmat++;
+ }
+ }
+
+ mfdatatot += me->totface;
+ }
+ }
+ base= base->next;
+ }
+
+ RG.cent[0]= (RG.min[0]+ RG.max[0])/2;
+ RG.cent[1]= (RG.min[1]+ RG.max[1])/2;
+ RG.cent[2]= (RG.min[2]+ RG.max[2])/2;
+ RG.size[0]= (RG.max[0]- RG.min[0]);
+ RG.size[1]= (RG.max[1]- RG.min[1]);
+ RG.size[2]= (RG.max[2]- RG.min[2]);
+ RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]);
+
+ RG.mfdata= MEM_callocN(sizeof(CustomData), "radiomfdata");
+ RG.mfdatanodes= MEM_mallocN(sizeof(RNode*)*mfdatatot, "radiomfdatanodes");
+ RG.mfdatatot= mfdatatot;
+
+ /* make patches */
+
+ RG.totelem= 0;
+ RG.totpatch= 0;
+ RG.totlamp= 0;
+ offs= 0;
+
+ base= (scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
+ if(base->object->type==OB_MESH) {
+ ob= base->object;
+ me= ob->data;
+ mface= me->mface;
+ tface= me->mtface;
+
+ index= -1;
+
+ CustomData_merge(&me->fdata, RG.mfdata, CD_MASK_DERIVEDMESH,
+ CD_DEFAULT, mfdatatot);
+
+ for(a=0; a<me->totface; a++, mface++) {
+ tf= tface? tface+a: NULL;
+
+ if (tf && (tf->mode & TF_INVISIBLE))
+ continue;
+
+ rp= callocPatch();
+ BLI_addtail(&(RG.patchbase), rp);
+ rp->from= ob;
+
+ if(mface->v4) rp->type= 4;
+ else rp->type= 3;
+
+ rp->first= rn= callocNode();
+
+ if(mface->flag & ME_SMOOTH) rp->f1= RAD_NO_SPLIT;
+
+ /* temporal: we store the venoco in the node */
+ rn->v1= (float *)(RG.verts+mface->v1+offs);
+ v1= (RG.verts+mface->v1+offs)->v;
+ rn->v2= (float *)(RG.verts+mface->v2+offs);
+ v2= (RG.verts+mface->v2+offs)->v;
+ rn->v3= (float *)(RG.verts+mface->v3+offs);
+ v3= (RG.verts+mface->v3+offs)->v;
+
+ if(mface->v4) {
+ rn->v4= (float *)(RG.verts+mface->v4+offs);
+ v4= (RG.verts+mface->v4+offs)->v;
+ }
+ rn->par= rp;
+ rn->f= RAD_PATCH; /* this node is a Patch */
+ rn->type= rp->type;
+
+ if(rn->type==4) {
+ rp->area= AreaQ3Dfl(v1, v2, v3, v4);
+ CalcNormFloat4(v1, v2, v3, v4, rp->norm);
+ }
+ else {
+ rp->area= AreaT3Dfl(v1, v2, v3);
+ CalcNormFloat(v1, v2, v3, rp->norm);
+ }
+
+ rn->area= rp->area;
+
+ /* color and emit */
+ if(mface->mat_nr != index) {
+ index= mface->mat_nr;
+ ma= give_current_material(ob, index+1);
+ if(ma==0) ma= &defmaterial;
+ }
+ rp->ref[0]= ma->r;
+ rp->ref[1]= ma->g;
+ rp->ref[2]= ma->b;
+
+ if(ma->emit) RG.totlamp++;
+
+ rp->emit[0]= rp->emit[1]= rp->emit[2]= ma->emit;
+ rp->emit[0]*= rp->ref[0];
+ rp->emit[1]*= rp->ref[1];
+ rp->emit[2]*= rp->ref[2];
+
+// uncommented, this is not satisfying, but i leave it in code for now (ton)
+// if(ma->translucency!=0.0) rn->f |= RAD_TWOSIDED;
+
+ nodevert= (VeNoCo **)&(rn->v1);
+ for(b=0; b<rp->type; b++) {
+ rp->cent[0]+= (*nodevert)->v[0];
+ rp->cent[1]+= (*nodevert)->v[1];
+ rp->cent[2]+= (*nodevert)->v[2];
+ nodevert++;
+ }
+ rp->cent[0]/= (float)rp->type;
+ rp->cent[1]/= (float)rp->type;
+ rp->cent[2]/= (float)rp->type;
+
+ /* for reconstruction materials */
+ rp->matindex= materialIndex(ma);
+ if(rp->matindex==-1) rp->matindex= 1;
+
+ /* these RNode's are stored now for later use in rad_addmesh
+ they should not get deleted before that */
+ rn->orig= RG.totelem;
+ RG.mfdatanodes[RG.totelem]= rn;
+
+ CustomData_copy_data(&me->fdata, RG.mfdata, a, RG.totelem, 1);
+
+ RG.totelem++;
+ RG.totpatch++;
+ }
+
+ offs+= me->totvert;
+ }
+ }
+ base= base->next;
+ }
+
+ splitconnected();
+ setedgepointers();
+
+ makeGlobalElemArray();
+ pseudoAmb();
+ rad_setlimits(scene);
+}
+
+void setparelem(RNode *rn, RPatch *par)
+{
+
+ if(rn->down1) {
+ setparelem(rn->down1, par);
+ setparelem(rn->down2, par);
+ }
+ else {
+ rn->par= par;
+ }
+}
+
+void countelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ countelem(rn->down1);
+ countelem(rn->down2);
+ }
+ else RG.totelem++;
+}
+
+void countglobaldata()
+{
+ /* counts elements and patches*/
+ RPatch *rp;
+
+ RG.totelem= RG.totpatch= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ RG.totpatch++;
+ countelem(rp->first);
+ rp= rp->next;
+ }
+}
+
+void addelem(RNode ***el, RNode *rn, RPatch *rp)
+{
+ if(rn->down1) {
+ addelem(el, rn->down1, rp);
+ addelem(el, rn->down2, rp);
+ }
+ else {
+ rn->par= rp;
+ **el= rn;
+ (*el)++;
+ }
+}
+
+void makeGlobalElemArray()
+{
+ /* always called when # of elements change */
+ RPatch *rp;
+ RNode **el;
+
+ countglobaldata();
+
+ if(RG.elem) MEM_freeN(RG.elem);
+ if(RG.totelem) {
+ el= RG.elem= MEM_mallocN(sizeof(void *)*RG.totelem, "makeGlobalElemArray");
+ }
+ else {
+ RG.elem= 0;
+ return;
+ }
+
+ /* recursive adding elements */
+ rp= RG.patchbase.first;
+ while(rp) {
+ addelem(&el, rp->first, rp);
+ rp= rp->next;
+ }
+
+ /* formfactor array */
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ if(RG.totelem)
+ RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors");
+ else
+ RG.formfactors= 0;
+}
+
+void splitpatch(RPatch *old) /* in case of overflow during shoot */
+{
+ RNode *rn;
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ rn= old->first;
+ if(rn->down1==0) return;
+ rn= rn->down1;
+
+ old->unshot[0]/=2.0;
+ old->unshot[1]/=2.0;
+ old->unshot[2]/=2.0;
+ setnodeflags(old->first, 2, 0);
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ rn= old->first->down2;
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ BLI_remlink(&RG.patchbase, old);
+ freePatch(old);
+}
+
+
+void addpatch(RPatch *old, RNode *rn)
+{
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ if(rn->down1) {
+ addpatch(old, rn->down1);
+ addpatch(old, rn->down2);
+ }
+ else {
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ rn->par= rp;
+ }
+}
+
+void converttopatches()
+{
+ /* chacks patches list, if node subdivided: new patch */
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->first->down1) {
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void subdiv_elements()
+{
+ RNode **el, *rn;
+ int a, toobig= 1;
+
+ rad_init_energy();
+
+ /* first maxsize elements */
+
+ while(toobig) {
+ toobig= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ if(rn->area>RG.elemmin) {
+ subdivideNode(rn, 0);
+ if(rn->down1 ) {
+ toobig= 1;
+ if(rn->down1->area>RG.elemmin)
+ subdivideNode( rn->down1, 0);
+ if(rn->down2->area>RG.elemmin)
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ }
+ if(toobig) makeGlobalElemArray();
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ subdivideNode(rn, 0);
+ if( rn->down1 ) {
+ subdivideNode( rn->down1, 0);
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ makeGlobalElemArray();
+}
+
+void subdividelamps()
+{
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void maxsizePatches()
+{
+ RPatch *rp;
+ int toobig= 1;
+
+ while(toobig) {
+ toobig= 0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp->area>RG.patchmax) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) toobig= 1;
+ }
+ rp= rp->next;
+ }
+
+ if(toobig) converttopatches();
+ }
+
+ /* count lamps */
+ rp= RG.patchbase.first;
+ RG.totlamp= 0;
+ while(rp) {
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ RG.totlamp++;
+ }
+ rp= rp->next;
+ }
+ makeGlobalElemArray();
+}
+
+
+
diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c
new file mode 100644
index 00000000000..d33bbc90ee3
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radrender.c
@@ -0,0 +1,530 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* radrender.c, aug 2003
+ *
+ * Most of the code here is copied from radiosity code, to optimize for renderfaces.
+ * Shared function calls mostly reside in radfactors.c
+ * No adaptive subdivision takes place
+ *
+ * - do_radio_render(); main call, extern
+ * - initradfaces(); add radface structs in render faces, init radio globals
+ * -
+ * - initradiosity(); LUTs
+ * - inithemiwindows();
+ * - progressiverad(); main itteration loop
+ * - hemi zbuffers
+ * - calc rad factors
+ *
+ * - closehemiwindows();
+ * - freeAllRad();
+ * - make vertex colors
+ *
+ * - during render, materials use totrad as ambient replacement
+ * - free radfaces
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "radio.h"
+
+/* the radiosity module uses internal includes from render! */
+#include "renderpipeline.h"
+#include "render_types.h"
+#include "renderdatabase.h"
+
+
+/* only needed now for a print, if its useful move to RG */
+static float maxenergy;
+
+/* find the face with maximum energy to become shooter */
+/* nb: _rr means rad-render version of existing radio call */
+static void findshoot_rr(Render *re, VlakRen **shoot_p, RadFace **shootrf_p)
+{
+ RadFace *rf, *shootrf, **radface;
+ ObjectRen *obr;
+ VlakRen *vlr=NULL, *shoot;
+ float energy;
+ int a;
+
+ shoot= NULL;
+ shootrf= NULL;
+ maxenergy= 0.0;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ rf->flag &= ~RAD_SHOOT;
+
+ energy= rf->unshot[0]*rf->area;
+ energy+= rf->unshot[1]*rf->area;
+ energy+= rf->unshot[2]*rf->area;
+
+ if(energy>maxenergy) {
+ shoot= vlr;
+ shootrf= rf;
+ maxenergy= energy;
+ }
+ }
+ }
+ }
+
+ if(shootrf) {
+ maxenergy/= RG.totenergy;
+ if(maxenergy<RG.convergence) {
+ *shoot_p= NULL;
+ *shootrf_p= NULL;
+ return;
+ }
+ shootrf->flag |= RAD_SHOOT;
+ }
+
+ *shoot_p= shoot;
+ *shootrf_p= shootrf;
+}
+
+static void backface_test_rr(Render *re, VlakRen *shoot, RadFace *shootrf)
+{
+ ObjectRen *obr;
+ VlakRen *vlr=NULL;
+ RadFace *rf, **radface;
+ float tvec[3];
+ int a;
+
+ /* backface testing */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+ if(vlr != shoot && (radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ VecSubf(tvec, shootrf->cent, rf->cent);
+
+ if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0)
+ rf->flag |= RAD_BACKFACE;
+ }
+ }
+ }
+}
+
+static void clear_backface_test_rr(Render *re)
+{
+ ObjectRen *obr;
+ VlakRen *vlr=NULL;
+ RadFace *rf, **radface;
+ int a;
+
+ /* backface flag clear */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ rf->flag &= ~RAD_BACKFACE;
+ }
+ }
+ }
+}
+
+extern RadView hemitop, hemiside; // radfactors.c
+
+/* hemi-zbuffering, delivers formfactors array */
+static void makeformfactors_rr(Render *re, VlakRen *shoot, RadFace *shootrf)
+{
+ ObjectRen *obr;
+ VlakRen *vlr=NULL;
+ RadFace *rf, **radface;
+ float len, vec[3], up[3], side[3], tar[5][3], *fp;
+ int a;
+
+ memset(RG.formfactors, 0, sizeof(float)*RG.totelem);
+
+ /* set up hemiview */
+ /* first: upvector for hemitop, we use diagonal hemicubes to prevent aliasing */
+
+ VecSubf(vec, shoot->v1->co, shootrf->cent);
+ Crossf(up, shootrf->norm, vec);
+ len= Normalize(up);
+
+ VECCOPY(hemitop.up, up);
+ VECCOPY(hemiside.up, shootrf->norm);
+
+ Crossf(side, shootrf->norm, up);
+
+ /* five targets */
+ VecAddf(tar[0], shootrf->cent, shootrf->norm);
+ VecAddf(tar[1], shootrf->cent, up);
+ VecSubf(tar[2], shootrf->cent, up);
+ VecAddf(tar[3], shootrf->cent, side);
+ VecSubf(tar[4], shootrf->cent, side);
+
+ /* camera */
+ VECCOPY(hemiside.cam, shootrf->cent);
+ VECCOPY(hemitop.cam, shootrf->cent);
+
+ /* do it! */
+ VECCOPY(hemitop.tar, tar[0]);
+ hemizbuf(&hemitop);
+
+ for(a=1; a<5; a++) {
+ VECCOPY(hemiside.tar, tar[a]);
+ hemizbuf(&hemiside);
+ }
+
+ /* convert factors to real radiosity */
+ fp= RG.formfactors;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ if(*fp!=0.0 && rf->area!=0.0) {
+ *fp *= shootrf->area/rf->area;
+ if(*fp>1.0) *fp= 1.0001;
+ }
+ fp++;
+ }
+ }
+ }
+}
+
+/* based at RG.formfactors array, distribute shoot energy over other faces */
+static void applyformfactors_rr(Render *re, VlakRen *shoot, RadFace *shootrf)
+{
+ ObjectRen *obr;
+ VlakRen *vlr=NULL;
+ RadFace *rf, **radface;
+ float *fp, *ref, unr, ung, unb, r, g, b;
+ int a;
+
+ unr= shootrf->unshot[0];
+ ung= shootrf->unshot[1];
+ unb= shootrf->unshot[2];
+
+ fp= RG.formfactors;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ if(*fp!= 0.0) {
+
+ ref= &(vlr->mat->r);
+
+ r= (*fp)*unr*ref[0];
+ g= (*fp)*ung*ref[1];
+ b= (*fp)*unb*ref[2];
+
+ // if(rf->flag & RAD_BACKFACE) {
+
+ rf->totrad[0]+= r;
+ rf->totrad[1]+= g;
+ rf->totrad[2]+= b;
+
+ rf->unshot[0]+= r;
+ rf->unshot[1]+= g;
+ rf->unshot[2]+= b;
+ }
+ fp++;
+ }
+ }
+ }
+ /* shoot energy has been shot */
+ shootrf->unshot[0]= shootrf->unshot[1]= shootrf->unshot[2]= 0.0;
+}
+
+
+/* main loop for itterations */
+static void progressiverad_rr(Render *re)
+{
+ VlakRen *shoot;
+ RadFace *shootrf;
+ float unshot[3];
+ int it= 0;
+
+ findshoot_rr(re, &shoot, &shootrf);
+ while( shoot ) {
+
+ /* backfaces receive no energy, but are zbuffered... */
+ backface_test_rr(re, shoot, shootrf);
+
+ /* ...unless it's two sided */
+ if(shootrf->flag & RAD_TWOSIDED) {
+ VECCOPY(unshot, shootrf->unshot);
+ VecNegf(shootrf->norm);
+ makeformfactors_rr(re, shoot, shootrf);
+ applyformfactors_rr(re, shoot, shootrf);
+ VecNegf(shootrf->norm);
+ VECCOPY(shootrf->unshot, unshot);
+ }
+
+ /* hemi-zbuffers */
+ makeformfactors_rr(re, shoot, shootrf);
+ /* based at RG.formfactors array, distribute shoot energy over other faces */
+ applyformfactors_rr(re, shoot, shootrf);
+
+ it++;
+ re->timecursor(re->tch, it);
+
+ clear_backface_test_rr(re);
+
+ if(re->test_break(re->tbh)) break;
+ if(RG.maxiter && RG.maxiter<=it) break;
+
+ findshoot_rr(re, &shoot, &shootrf);
+ }
+ printf(" Unshot energy:%f\n", 1000.0*maxenergy);
+
+ re->timecursor(re->tch, re->scene->r.cfra);
+}
+
+static RadFace *radfaces=NULL;
+
+static void initradfaces(Render *re)
+{
+ ObjectRen *obr;
+ VlakRen *vlr= NULL;
+ RadFace *rf, **radface;
+ int a, b;
+
+ /* globals */
+ RG.totenergy= 0.0;
+ RG.totpatch= 0; // we count initial emittors here
+ RG.totelem= 0; // total # faces are put here (so we can use radfactors.c calls)
+ /* size is needed for hemicube clipping */
+ RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20;
+ RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
+
+ /* count first for fast malloc */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->mat->mode & MA_RADIO) {
+ if(vlr->mat->emit > 0.0) {
+ RG.totpatch++;
+ }
+ RG.totelem++;
+ }
+ }
+ }
+
+printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch);
+ if(RG.totelem==0 || RG.totpatch==0) return;
+
+ /* make/init radfaces */
+ rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces");
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->mat->mode & MA_RADIO) {
+
+ /* during render, vlr->n gets flipped/corrected, we cannot have that */
+ if (obr->ob->transflag & OB_NEG_SCALE){
+ /* The object has negative scale that will cause the normals to flip.
+ To counter this unwanted normal flip, swap vertex 2 and 4 for a quad
+ or vertex 2 and 3 (see flip_face) for a triangle in the call to CalcNormFloat4
+ in order to flip the normals back to the way they were in the original mesh. */
+ if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v4->co, vlr->v3->co, vlr->v2->co, rf->norm);
+ else CalcNormFloat(vlr->v1->co, vlr->v3->co, vlr->v2->co, rf->norm);
+ }else{
+ if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
+ else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
+ }
+
+ rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
+ rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
+ rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
+ VECCOPY(rf->unshot, rf->totrad);
+
+ if(vlr->v4) {
+ rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+ CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+ }
+ else {
+ rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
+ CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
+ }
+
+ RG.totenergy+= rf->unshot[0]*rf->area;
+ RG.totenergy+= rf->unshot[1]*rf->area;
+ RG.totenergy+= rf->unshot[2]*rf->area;
+
+ for(b=0; b<3; b++) {
+ RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
+ RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
+ }
+
+ // uncommented; this isnt satisfying, but i leave it in the code for now (ton)
+ // if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
+
+ radface=RE_vlakren_get_radface(obr, vlr, 1);
+ *radface= rf++;
+ }
+ }
+ }
+ RG.size[0]= (RG.max[0]- RG.min[0]);
+ RG.size[1]= (RG.max[1]- RG.min[1]);
+ RG.size[2]= (RG.max[2]- RG.min[2]);
+ RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]);
+
+ /* formfactor array */
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ if(RG.totelem)
+ RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors");
+ else
+ RG.formfactors= NULL;
+
+}
+
+static void vecaddfac(float *vec, float *v1, float *v2, float fac)
+{
+ vec[0]= v1[0] + fac*v2[0];
+ vec[1]= v1[1] + fac*v2[1];
+ vec[2]= v1[2] + fac*v2[2];
+
+}
+
+/* unused now, doesnt work..., find it in cvs of nov 2005 or older */
+/* static void filter_rad_values(void) */
+
+
+static void make_vertex_rad_values(Render *re)
+{
+ ObjectRen *obr;
+ VertRen *v1=NULL;
+ VlakRen *vlr=NULL;
+ RadFace *rf, **radface;
+ float *col;
+ int a;
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */
+
+ /* accumulate vertexcolors */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+
+ /* apply correction */
+ rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
+ rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
+ rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
+
+ /* correct rf->rad values for color */
+ if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
+ if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
+ if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
+
+ col= RE_vertren_get_rad(obr, vlr->v1, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+
+ col= RE_vertren_get_rad(obr, vlr->v2, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+
+ col= RE_vertren_get_rad(obr, vlr->v3, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+
+ if(vlr->v4) {
+ col= RE_vertren_get_rad(obr, vlr->v4, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+ }
+ }
+ }
+
+ /* make vertex colors */
+ for(a=0; a<obr->totvert; a++) {
+ if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++;
+
+ col= RE_vertren_get_rad(obr, v1, 0);
+ if(col && col[3]>0.0) {
+ col[0]/= col[3];
+ col[1]/= col[3];
+ col[2]/= col[3];
+ }
+ }
+ }
+}
+
+/* main call, extern */
+void do_radio_render(Render *re)
+{
+ if(re->scene->radio==NULL) add_radio(re->scene);
+ freeAllRad(re->scene); /* just in case radio-tool is still used */
+
+ set_radglobal(re->scene); /* init the RG struct */
+ RG.re= re; /* only used by hemizbuf(), prevents polluting radio code all over */
+
+ initradfaces(re); /* add radface structs to render faces */
+ if(RG.totenergy>0.0) {
+
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views, need RG.maxsize for clipping */
+
+ progressiverad_rr(re); /* main radio loop */
+
+ make_vertex_rad_values(re); /* convert face energy to vertex ones */
+
+ }
+
+ freeAllRad(re->scene); /* luts, hemis, sets vars at zero */
+}
+
+/* free call, after rendering, extern */
+void end_radio_render(void)
+{
+ if(radfaces) MEM_freeN(radfaces);
+ radfaces= NULL;
+}
+
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 15b59f2c8cc..20eea0c98bd 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -47,8 +47,7 @@ struct Render;
struct MTex;
struct ImBuf;
-// RADIO REMOVED, Maybe this will be useful later
-//void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re);
+void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re);
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index a00cd2211fc..98e5819c0d3 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -104,6 +104,7 @@
#include "rendercore.h"
#include "renderdatabase.h"
#include "renderpipeline.h"
+#include "radio.h"
#include "shadbuf.h"
#include "shading.h"
#include "strand.h"
@@ -1885,9 +1886,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0)
continue;
- if(psys->parent)
- Mat4MulVecfl(psys->parent->obmat, state.co);
-
VECCOPY(loc,state.co);
if(part->ren_as!=PART_DRAW_BB)
MTC_Mat4MulVecfl(re->viewmat,loc);
@@ -4310,9 +4308,8 @@ void RE_Database_Free(Render *re)
}
free_mesh_orco_hash(re);
-#if 0 /* radio can be redone better */
+
end_radio_render();
-#endif
end_render_materials();
end_render_textures();
@@ -4739,11 +4736,10 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
/* yafray: 'direct' radiosity, environment maps and raytree init not needed for yafray render */
/* although radio mode could be useful at some point, later */
if (re->r.renderer==R_INTERN) {
-#if 0 /* RADIO was removed */
/* RADIO (uses no R anymore) */
if(!re->test_break(re->tbh))
if(re->r.mode & R_RADIO) do_radio_render(re);
-#endif
+
/* raytree */
if(!re->test_break(re->tbh)) {
if(re->r.mode & R_RAYTRACE) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index ccc793e4235..07560edb76b 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -46,7 +46,6 @@
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
-#include "BKE_pointcache.h"
#include "MEM_guardedalloc.h"
@@ -62,6 +61,7 @@
#include "intern/openexr/openexr_multi.h"
#include "RE_pipeline.h"
+#include "radio.h"
/* internal */
#include "render_types.h"
@@ -2413,21 +2413,6 @@ static int is_rendering_allowed(Render *re)
return 1;
}
-static void update_physics_cache(Render *re, Scene *scene)
-{
- PTCacheBaker baker;
-
- baker.scene = scene;
- baker.pid = NULL;
- baker.bake = 0;
- baker.render = 1;
- baker.quick_step = 1;
- baker.break_test = re->test_break;
- baker.break_data = re->tbh;
- baker.progressbar = NULL;
-
- BKE_ptcache_make_cache(&baker);
-}
/* evaluating scene options for general Blender render */
static int render_initialize_from_scene(Render *re, Scene *scene, int anim)
{
@@ -2465,9 +2450,6 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim)
/* check all scenes involved */
tag_scenes_for_render(re);
-
- /* make sure dynamics are up to date */
- update_physics_cache(re, scene);
if(scene->r.scemode & R_SINGLE_LAYER)
push_render_result(re);
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 21c3977fc0b..b68cecce7bd 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -49,12 +49,14 @@
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_material_types.h"
#include "BKE_global.h"
#include "BKE_material.h"
#include "BKE_utildefines.h"
+#include "radio_types.h"
+#include "radio.h" /* needs RG, some root data for radiosity */
+
#include "RE_render_ext.h"
/* local includes */
@@ -2299,6 +2301,110 @@ static int hashlist_projectvert(float *v1, float winmat[][4], float *hoco)
return buck->clip;
}
+/* used for booth radio 'tool' as during render */
+void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Render *re)
+{
+ ZSpan zspan;
+ float hoco[4][4], winmat[4][4];
+ int a, zvlnr;
+ int c1, c2, c3, c4= 0;
+
+ if(rg_totelem==0) return;
+
+ hashlist_projectvert(NULL, winmat, NULL);
+
+ /* needed for projectvert */
+ MTC_Mat4MulMat4(winmat, vw->viewmat, vw->winmat);
+
+ /* 1.0f for clipping in clippyra()... bad stuff actually */
+ zbuf_alloc_span(&zspan, vw->rectx, vw->recty, 1.0f);
+ zspan.zmulx= ((float)vw->rectx)/2.0;
+ zspan.zmuly= ((float)vw->recty)/2.0;
+ zspan.zofsx= -0.5f;
+ zspan.zofsy= -0.5f;
+
+ /* the buffers */
+ zspan.rectz= (int *)vw->rectz;
+ zspan.rectp= (int *)vw->rect;
+ zspan.recto= MEM_callocN(sizeof(int)*vw->rectx*vw->recty, "radiorecto");
+ fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF);
+ fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF);
+
+ /* filling methods */
+ zspan.zbuffunc= zbuffillGL4;
+
+ if(rg_elem) { /* radio tool */
+ RNode **re, *rn;
+
+ re= rg_elem;
+ re+= (rg_totelem-1);
+ for(a= rg_totelem-1; a>=0; a--, re--) {
+ rn= *re;
+ if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */
+
+ if( rn->f & RAD_TWOSIDED) zvlnr= a;
+ else if( rn->f & RAD_BACKFACE) zvlnr= 0xFFFFFF;
+ else zvlnr= a;
+
+ c1= hashlist_projectvert(rn->v1, winmat, hoco[0]);
+ c2= hashlist_projectvert(rn->v2, winmat, hoco[1]);
+ c3= hashlist_projectvert(rn->v3, winmat, hoco[2]);
+
+ if(rn->v4) {
+ c4= hashlist_projectvert(rn->v4, winmat, hoco[3]);
+ }
+
+ if(rn->v4)
+ zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ else
+ zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ }
+ }
+ }
+ else { /* radio render */
+ ObjectRen *obr;
+ VlakRen *vlr=NULL;
+ RadFace **radface, *rf;
+ int totface=0;
+
+ /* note: radio render doesn't support duplis */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ hashlist_projectvert(NULL, NULL, NULL); /* clear hashlist */
+
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) {
+ rf= *radface;
+ if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */
+
+ if( rf->flag & RAD_TWOSIDED) zvlnr= totface;
+ else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */
+ else zvlnr= totface;
+
+ c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]);
+ c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]);
+ c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]);
+
+ if(vlr->v4) {
+ c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]);
+ }
+
+ if(vlr->v4)
+ zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ else
+ zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ }
+ totface++;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(zspan.recto);
+ zbuf_free_span(&zspan);
+}
+
void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity)
{
ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ffeb342df77..7acb2921bec 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -79,7 +79,7 @@ void WM_keymap_tweak (ListBase *lb, short type, short val, int modifier, short
ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid,
int spaceid, int regionid);
-const char *WM_key_event_string(short type);
+char *WM_key_event_string(short type);
char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len);
/* handlers */
@@ -129,8 +129,6 @@ int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op);
/* operator api */
void WM_operator_free (struct wmOperator *op);
-void WM_operator_stack_clear(struct bContext *C);
-
wmOperatorType *WM_operatortype_find(const char *idname);
wmOperatorType *WM_operatortype_first(void);
void WM_operatortype_append (void (*opfunc)(wmOperatorType*));
@@ -214,8 +212,8 @@ void WM_jobs_stop(struct wmWindowManager *wm, void *owner);
void WM_jobs_stop_all(struct wmWindowManager *wm);
/* clipboard */
-char *WM_clipboard_text_get(int selection);
-void WM_clipboard_text_set(char *buf, int selection);
+char *WM_clipboard_text_get(int selection);
+void WM_clipboard_text_set(char *buf, int selection);
#endif /* WM_API_H */
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 9b987cdfa51..739cfbcc1ac 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -58,6 +58,37 @@ enum {
WM_OP_EXEC_SCREEN
};
+/* ************** wmEvent ************************ */
+
+/* each event should have full modifier state */
+/* event comes from eventmanager and from keymap */
+typedef struct wmEvent {
+ struct wmEvent *next, *prev;
+
+ short type; /* event code itself (short, is also in keymap) */
+ short val; /* press, release, scrollvalue */
+ short x, y; /* mouse pointer position, screen coord */
+ short mval[2]; /* region mouse position, name convention pre 2.5 :) */
+ short prevx, prevy; /* previous mouse pointer position */
+ short unicode; /* future, ghost? */
+ char ascii; /* from ghost */
+ char pad;
+
+ /* modifier states */
+ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */
+ short keymodifier; /* rawkey modifier */
+
+ /* keymap item, set by handler (weak?) */
+ const char *keymap_idname;
+
+ /* custom data */
+ short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */
+ void *customdata; /* ascii, unicode, mouse coords, angles, vectors, dragdrop info */
+ short customdatafree;
+
+} wmEvent;
+
+
/* ************** wmKeyMap ************************ */
/* modifier */
diff --git a/source/blender/windowmanager/intern/Makefile b/source/blender/windowmanager/intern/Makefile
index 8f0f47c52d0..80ae58f9398 100644
--- a/source/blender/windowmanager/intern/Makefile
+++ b/source/blender/windowmanager/intern/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 7dec14664ae..37fdc9fa2c5 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -95,18 +95,6 @@ void wm_operator_register(wmWindowManager *wm, wmOperator *op)
}
-void WM_operator_stack_clear(bContext *C)
-{
- wmWindowManager *wm= CTX_wm_manager(C);
- wmOperator *op;
-
- while((op= wm->operators.first)) {
- BLI_remlink(&wm->operators, op);
- WM_operator_free(op);
- }
-
-}
-
/* ****************************************** */
void wm_check(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 286d1216f66..ea6a65859e5 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -49,7 +49,6 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
-#include "BKE_pointcache.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
@@ -235,8 +234,6 @@ void wm_event_do_notifiers(bContext *C)
for(base= scene->base.first; base; base= base->next) {
object_handle_update(scene, base->object);
}
-
- BKE_ptcache_quick_cache_all(scene);
}
}
CTX_wm_window_set(C, NULL);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 861080f30ba..d13d8ec6ccc 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -294,6 +294,8 @@ int WM_read_homefile(bContext *C, wmOperator *op)
G.relbase_valid = 0;
if (!from_memory) {
BLI_make_file_string(G.sce, tstr, home, ".B25.blend");
+ if(!BLI_exists(tstr))
+ BLI_make_file_string(G.sce, tstr, home, ".B.blend");
}
strcpy(scestr, G.sce); /* temporary store */
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 0bc35ffa9b2..adbc43e439d 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -58,6 +58,8 @@
#include "RE_pipeline.h" /* RE_ free stuff */
+#include "radio.h"
+
#ifndef DISABLE_PYTHON
#include "BPY_extern.h"
#endif
@@ -194,6 +196,9 @@ void WM_exit(bContext *C)
// BIF_freeRetarget();
BIF_freeTemplates(C);
BIF_freeSketch(C);
+
+ /* Context should still working here. but radio tool needs cleaning... */
+ freeAllRad(CTX_data_scene(C));
free_ttfont(); /* bke_font.h */
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index b914e63788d..7528321c7c5 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -44,7 +44,6 @@
#include "RNA_access.h"
#include "RNA_types.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -154,11 +153,315 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei
/* ***************** get string from key events **************** */
-const char *WM_key_event_string(short type)
+char *WM_key_event_string(short type)
{
- const char *name= NULL;
- if(RNA_enum_name(event_type_items, (int)type, &name))
- return name;
+ /* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */
+
+ switch(type) {
+ case AKEY:
+ return "A";
+ break;
+ case BKEY:
+ return "B";
+ break;
+ case CKEY:
+ return "C";
+ break;
+ case DKEY:
+ return "D";
+ break;
+ case EKEY:
+ return "E";
+ break;
+ case FKEY:
+ return "F";
+ break;
+ case GKEY:
+ return "G";
+ break;
+ case HKEY:
+ return "H";
+ break;
+ case IKEY:
+ return "I";
+ break;
+ case JKEY:
+ return "J";
+ break;
+ case KKEY:
+ return "K";
+ break;
+ case LKEY:
+ return "L";
+ break;
+ case MKEY:
+ return "M";
+ break;
+ case NKEY:
+ return "N";
+ break;
+ case OKEY:
+ return "O";
+ break;
+ case PKEY:
+ return "P";
+ break;
+ case QKEY:
+ return "Q";
+ break;
+ case RKEY:
+ return "R";
+ break;
+ case SKEY:
+ return "S";
+ break;
+ case TKEY:
+ return "T";
+ break;
+ case UKEY:
+ return "U";
+ break;
+ case VKEY:
+ return "V";
+ break;
+ case WKEY:
+ return "W";
+ break;
+ case XKEY:
+ return "X";
+ break;
+ case YKEY:
+ return "Y";
+ break;
+ case ZKEY:
+ return "Z";
+ break;
+
+ case ZEROKEY:
+ return "Zero";
+ break;
+ case ONEKEY:
+ return "One";
+ break;
+ case TWOKEY:
+ return "Two";
+ break;
+ case THREEKEY:
+ return "Three";
+ break;
+ case FOURKEY:
+ return "Four";
+ break;
+ case FIVEKEY:
+ return "Five";
+ break;
+ case SIXKEY:
+ return "Six";
+ break;
+ case SEVENKEY:
+ return "Seven";
+ break;
+ case EIGHTKEY:
+ return "Eight";
+ break;
+ case NINEKEY:
+ return "Nine";
+ break;
+
+ case LEFTCTRLKEY:
+ return "Leftctrl";
+ break;
+ case LEFTALTKEY:
+ return "Leftalt";
+ break;
+ case RIGHTALTKEY:
+ return "Rightalt";
+ break;
+ case RIGHTCTRLKEY:
+ return "Rightctrl";
+ break;
+ case RIGHTSHIFTKEY:
+ return "Rightshift";
+ break;
+ case LEFTSHIFTKEY:
+ return "Leftshift";
+ break;
+
+ case ESCKEY:
+ return "Esc";
+ break;
+ case TABKEY:
+ return "Tab";
+ break;
+ case RETKEY:
+ return "Ret";
+ break;
+ case SPACEKEY:
+ return "Space";
+ break;
+ case LINEFEEDKEY:
+ return "Linefeed";
+ break;
+ case BACKSPACEKEY:
+ return "Backspace";
+ break;
+ case DELKEY:
+ return "Del";
+ break;
+ case SEMICOLONKEY:
+ return "Semicolon";
+ break;
+ case PERIODKEY:
+ return "Period";
+ break;
+ case COMMAKEY:
+ return "Comma";
+ break;
+ case QUOTEKEY:
+ return "Quote";
+ break;
+ case ACCENTGRAVEKEY:
+ return "Accentgrave";
+ break;
+ case MINUSKEY:
+ return "Minus";
+ break;
+ case SLASHKEY:
+ return "Slash";
+ break;
+ case BACKSLASHKEY:
+ return "Backslash";
+ break;
+ case EQUALKEY:
+ return "Equal";
+ break;
+ case LEFTBRACKETKEY:
+ return "Leftbracket";
+ break;
+ case RIGHTBRACKETKEY:
+ return "Rightbracket";
+ break;
+
+ case LEFTARROWKEY:
+ return "Leftarrow";
+ break;
+ case DOWNARROWKEY:
+ return "Downarrow";
+ break;
+ case RIGHTARROWKEY:
+ return "Rightarrow";
+ break;
+ case UPARROWKEY:
+ return "Uparrow";
+ break;
+
+ case PAD2:
+ return "Numpad 2";
+ break;
+ case PAD4:
+ return "Numpad 4";
+ break;
+ case PAD6:
+ return "Numpad 6";
+ break;
+ case PAD8:
+ return "Numpad 8";
+ break;
+ case PAD1:
+ return "Numpad 1";
+ break;
+ case PAD3:
+ return "Numpad 3";
+ break;
+ case PAD5:
+ return "Numpad 5";
+ break;
+ case PAD7:
+ return "Numpad 7";
+ break;
+ case PAD9:
+ return "Numpad 9";
+ break;
+
+ case PADPERIOD:
+ return "Numpad .";
+ break;
+ case PADSLASHKEY:
+ return "Numpad /";
+ break;
+ case PADASTERKEY:
+ return "Numpad *";
+ break;
+
+ case PAD0:
+ return "Numpad 0";
+ break;
+ case PADMINUS:
+ return "Numpad -";
+ break;
+ case PADENTER:
+ return "Numpad Enter";
+ break;
+ case PADPLUSKEY:
+ return "Numpad +";
+ break;
+
+ case F1KEY:
+ return "F1";
+ break;
+ case F2KEY:
+ return "F2";
+ break;
+ case F3KEY:
+ return "F3";
+ break;
+ case F4KEY:
+ return "F4";
+ break;
+ case F5KEY:
+ return "F5";
+ break;
+ case F6KEY:
+ return "F6";
+ break;
+ case F7KEY:
+ return "F7";
+ break;
+ case F8KEY:
+ return "F8";
+ break;
+ case F9KEY:
+ return "F9";
+ break;
+ case F10KEY:
+ return "F10";
+ break;
+ case F11KEY:
+ return "F11";
+ break;
+ case F12KEY:
+ return "F12";
+ break;
+
+ case PAUSEKEY:
+ return "Pause";
+ break;
+ case INSERTKEY:
+ return "Insert";
+ break;
+ case HOMEKEY:
+ return "Home";
+ break;
+ case PAGEUPKEY:
+ return "Pageup";
+ break;
+ case PAGEDOWNKEY:
+ return "Pagedown";
+ break;
+ case ENDKEY:
+ return "End";
+ break;
+ }
return "";
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 7f9a2153dc3..46e9df10adc 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -145,6 +145,7 @@ char *WM_operator_pystring(wmOperator *op)
const char *arg_name= NULL;
PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
/* for building the string */
DynStr *dynstr= BLI_dynstr_new();
@@ -154,9 +155,10 @@ char *WM_operator_pystring(wmOperator *op)
BLI_dynstr_appendf(dynstr, "%s(", op->idname);
iterprop= RNA_struct_iterator_property(op->ptr->type);
+ RNA_property_collection_begin(op->ptr, iterprop, &iter);
- RNA_PROP_BEGIN(op->ptr, propptr, iterprop) {
- prop= propptr.data;
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -168,7 +170,8 @@ char *WM_operator_pystring(wmOperator *op)
MEM_freeN(buf);
first_iter = 0;
}
- RNA_PROP_END;
+
+ RNA_property_collection_end(&iter);
BLI_dynstr_append(dynstr, ")");
@@ -288,7 +291,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 300, 20, style);
- uiDefAutoButsRNA(C, layout, &ptr, 2);
+ uiDefAutoButsRNA(C, layout, &ptr);
uiPopupBoundsBlock(block, 4.0f, 0, 0);
uiEndBlock(C, block);
@@ -330,7 +333,7 @@ static uiBlock *wm_block_create_menu(bContext *C, ARegion *ar, void *arg_op)
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1);
layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 300, 20, style);
- uiDefAutoButsRNA(C, layout, op->ptr, 2);
+ uiDefAutoButsRNA(C, layout, op->ptr);
uiPopupBoundsBlock(block, 4.0f, 0, 0);
uiEndBlock(C, block);
@@ -399,7 +402,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
name[len]= '|';
}
- if(0==uiSearchItemAdd(items, name, ot, 0))
+ if(0==uiSearchItemAdd(items, name, ot))
break;
}
}
@@ -418,7 +421,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *arg_op)
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1);
but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, "");
- uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
+ uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb);
/* fake button, it holds space for search items */
uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
@@ -500,7 +503,7 @@ static void WM_OT_read_homefile(wmOperatorType *ot)
static int recentfile_exec(bContext *C, wmOperator *op)
{
- int event= RNA_int_get(op->ptr, "nr");
+ int event= RNA_enum_get(op->ptr, "nr");
// XXX wm in context is not set correctly after WM_read_file -> crash
// do it before for now, but is this correct with multiple windows?
@@ -554,7 +557,7 @@ static void WM_OT_open_recentfile(wmOperatorType *ot)
ot->exec= recentfile_exec;
ot->poll= WM_operator_winactive;
- RNA_def_property(ot->srna, "nr", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property(ot->srna, "nr", PROP_ENUM, PROP_NONE);
}
/* ********* main file *********** */
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 835fdca52fe..9bd55e1c5a7 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: mywindow.c 9584 2007-01-03 13:45:03Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/windowmanager/wm_cursors.h b/source/blender/windowmanager/wm_cursors.h
index 3d1b49983ed..1a1a0d0b71d 100644
--- a/source/blender/windowmanager/wm_cursors.h
+++ b/source/blender/windowmanager/wm_cursors.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BIF_cursors.h 7739 2006-06-15 14:22:59Z broken $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h
index c0c492018ff..dfba9c27f17 100644
--- a/source/blender/windowmanager/wm_subwindow.h
+++ b/source/blender/windowmanager/wm_subwindow.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: wm_subwindow.h 21247 2009-06-29 21:50:53Z jaguarandi $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index ade5a2a64a8..4701eba810f 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -198,7 +198,7 @@ ADD_DEPENDENCIES(blender makesdna)
FILE(READ ${CMAKE_BINARY_DIR}/cmake_blender_libs.txt BLENDER_LINK_LIBS)
-SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} bf_windowmanager bf_editors blender_render)
+SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} bf_windowmanager bf_editors blender_render blender_radiosity)
IF(WITH_ELBEEM)
SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} bf_elbeem)
@@ -218,6 +218,7 @@ IF(UNIX)
bf_ghost
bf_string
blender_render
+ blender_radiosity
blender_ONL
bf_python
bf_gen_python
@@ -237,6 +238,7 @@ IF(UNIX)
bf_kernel
bf_decimation
bf_elbeem
+ bf_yafray
bf_IK
bf_memutil
bf_guardedalloc
@@ -262,7 +264,10 @@ IF(UNIX)
bf_ngnetwork
extern_bullet
bf_loopbacknetwork
+ bf_sumo
bf_common
+ extern_solid
+ extern_qhull
bf_moto
bf_python
bf_gen_python
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index fb222b419c3..44678cb73eb 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -65,14 +65,6 @@
#include "SYS_System.h"
-#include "GPU_extensions.h"
-#include "Value.h"
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
/***/
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
@@ -85,13 +77,21 @@ extern "C" {
//XXX #include "BIF_scrarea.h"
#include "BKE_main.h"
+//#include "BKE_context.h"
#include "BLI_blenlib.h"
#include "BLO_readfile.h"
#include "DNA_scene_types.h"
/***/
+#include "GPU_extensions.h"
+#include "Value.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
//XXX #include "BSE_headerbuttons.h"
-#include "BKE_context.h"
#include "../../blender/windowmanager/WM_types.h"
#include "../../blender/windowmanager/wm_window.h"
#include "../../blender/windowmanager/wm_event_system.h"
@@ -118,10 +118,19 @@ static BlendFileData *load_game_data(char *filename)
return bfd;
}
+
+/* screw it, BKE_context.h is complaining! */
+extern "C" struct wmWindow *CTX_wm_window(const bContext *C);
+extern "C" struct ScrArea *CTX_wm_area(const bContext *C);
+extern "C" struct ARegion *CTX_wm_region(const bContext *C);
+extern "C" struct Scene *CTX_data_scene(const bContext *C);
+extern "C" struct Main *CTX_data_main(const bContext *C);
+
extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_framing)
{
/* context values */
struct wmWindow *win= CTX_wm_window(C);
+ struct ScrArea *area= CTX_wm_area(C); // curarea
struct ARegion *ar= CTX_wm_region(C);
struct Scene *scene= CTX_data_scene(C);
struct Main* maggie1= CTX_data_main(C);
@@ -150,8 +159,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami
do
{
- View3D *v3d= CTX_wm_view3d(C);
- RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ View3D *v3d= (View3D*) area->spacedata.first;
+ RegionView3D *rv3d= (RegionView3D*) ar->regiondata;
// get some preferences
SYS_SystemHandle syshandle = SYS_GetSystem();
@@ -230,12 +239,13 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami
scene->camera= v3d->camera;
}
+
// some blender stuff
MT_CmMatrix4x4 projmat;
MT_CmMatrix4x4 viewmat;
float camzoom;
int i;
-
+
for (i = 0; i < 16; i++)
{
float *viewmat_linear= (float*) rv3d->viewmat;
@@ -247,7 +257,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami
projmat.setElem(i, projmat_linear[i]);
}
- if(rv3d->persp==V3D_CAMOB) {
+ if(v3d->persp==V3D_CAMOB) {
camzoom = (1.41421 + (rv3d->camzoom / 50.0));
camzoom *= camzoom;
}
@@ -338,10 +348,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami
if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
{
- if (rv3d->persp != V3D_CAMOB)
+ if (v3d->persp != V3D_CAMOB)
{
ketsjiengine->EnableCameraOverride(startscenename);
- ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == V3D_ORTHO));
+ ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO));
ketsjiengine->SetCameraOverrideProjectionMatrix(projmat);
ketsjiengine->SetCameraOverrideViewMatrix(viewmat);
ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
@@ -577,6 +587,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami
}
extern "C" void StartKetsjiShellSimulation(struct wmWindow *win,
+ struct ScrArea *area,
struct ARegion *ar,
char* scenename,
struct Main* maggie,
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index 2874a0273cc..3b690a21584 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -19,8 +19,7 @@ SET(INC
../../../source/blender/windowmanager
../../../source/blender
../../../source/blender/include
- ../../../source/blender/makesdna
- ../../../source/blender/makesrna
+ ../../../source/blender/makesdna
../../../source/gameengine/Rasterizer
../../../source/gameengine/GameLogic
../../../source/gameengine/Expressions
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index 360794ceb33..aa83d17a03a 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -28,13 +28,11 @@
#include "KX_BlenderCanvas.h"
#include "DNA_screen_types.h"
-#include "stdio.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-
KX_BlenderCanvas::KX_BlenderCanvas(struct wmWindow *win, ARegion *ar) :
m_win(win),
m_ar(ar)
diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile
index ffa99a0c1b2..f5486bae87b 100644
--- a/source/gameengine/BlenderRoutines/Makefile
+++ b/source/gameengine/BlenderRoutines/Makefile
@@ -36,6 +36,8 @@ include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(NAN_SUMO)/include -I$(NAN_SOLID)/include
+CPPFLAGS += -I$(NAN_SOLID)
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
CPPFLAGS += -I$(NAN_FUZZICS)/include
@@ -54,7 +56,6 @@ CPPFLAGS += -I../../blender/render/extern/include
CPPFLAGS += -I../../blender/blenloader
CPPFLAGS += -I../../blender/blenfont
CPPFLAGS += -I../../blender/gpu
-CPPFLAGS += -I../../blender/makesrna
CPPFLAGS += -I../Converter
CPPFLAGS += -I../Expressions
CPPFLAGS += -I../GameLogic
@@ -66,6 +67,7 @@ CPPFLAGS += -I../../kernel/gen_system
CPPFLAGS += -I../Network
CPPFLAGS += -I../Network/LoopBackNetwork
CPPFLAGS += -I../Physics/common
+CPPFLAGS += -I../Physics/Sumo
CPPFLAGS += -I.
ifeq ($(OS),windows)
diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript
index fc12f453d86..a0cc3af3611 100644
--- a/source/gameengine/BlenderRoutines/SConscript
+++ b/source/gameengine/BlenderRoutines/SConscript
@@ -11,8 +11,7 @@ incs += ' #intern/ghost/include'
incs += ' #intern/moto/include #source/gameengine/Ketsji #source/blender/blenlib'
incs += ' #source/blender/blenkernel #source/blender'
incs += ' #source/blender/blenfont #source/blender/editors/include'
-incs += ' #source/blender/makesdna #source/blender/makesrna'
-incs += ' #source/gameengine/Rasterizer #source/gameengine/GameLogic'
+incs += ' #source/blender/makesdna #source/gameengine/Rasterizer #source/gameengine/GameLogic'
incs += ' #source/gameengine/Expressions #source/gameengine/Network'
incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common'
incs += ' #source/gameengine/Physics/Bullet'
@@ -21,6 +20,11 @@ incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader'
incs += ' #extern/glew/include #source/blender/gpu'
incs += ' #source/blender/windowmanager'
+if env['WITH_BF_SOLID']:
+ incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include'
+ incs += ' ' + env['BF_SOLID_INC']
+ defs.append('USE_SUMO_SOLID')
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt
index f546a31fb2e..fd05858710d 100644
--- a/source/gameengine/CMakeLists.txt
+++ b/source/gameengine/CMakeLists.txt
@@ -38,6 +38,7 @@ ADD_SUBDIRECTORY(Rasterizer)
ADD_SUBDIRECTORY(Rasterizer/RAS_OpenGLRasterizer)
ADD_SUBDIRECTORY(SceneGraph)
ADD_SUBDIRECTORY(Physics/Bullet)
+ADD_SUBDIRECTORY(Physics/Sumo)
ADD_SUBDIRECTORY(VideoTexture)
IF(WITH_PLAYER)
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index bed99a4f502..c0d28d28bda 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -446,7 +446,7 @@ PyObject* BL_ActionActuator::PyGetAction(PyObject* args,
ShowDeprecationWarning("getAction()", "the action property");
if (m_action){
- return PyUnicode_FromString(m_action->id.name+2);
+ return PyString_FromString(m_action->id.name+2);
}
Py_RETURN_NONE;
}
@@ -796,7 +796,7 @@ PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args,
}
PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) {
- char *string= _PyUnicode_AsString(value);
+ char *string= PyString_AsString(value);
if (!string) {
PyErr_SetString(PyExc_TypeError, "expected a single string");
@@ -888,7 +888,7 @@ PyObject* BL_ActionActuator::PySetType(PyObject* args,
PyObject* BL_ActionActuator::PyGetContinue() {
ShowDeprecationWarning("getContinue()", "the continue property");
- return PyLong_FromSsize_t((long)(m_end_reset==0));
+ return PyInt_FromLong((long)(m_end_reset==0));
}
PyObject* BL_ActionActuator::PySetContinue(PyObject* value) {
@@ -962,9 +962,9 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
else {
MT_Vector3 loc;
MT_Vector3 size;
- MT_Quaternion quat;
+ MT_Vector4 quat;
- if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyQuatTo(pyquat, quat))
+ if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyVecTo(pyquat, quat))
return NULL;
// same as above
@@ -977,7 +977,7 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
// for some reason loc.setValue(pchan->loc) fails
pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2];
pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2];
- pchan->quat[0]= quat[3]; pchan->quat[1]= quat[0]; pchan->quat[2]= quat[1]; pchan->quat[3]= quat[2]; /* notice xyzw -> wxyz is intentional */
+ pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3];
}
pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
@@ -1005,15 +1005,19 @@ PyTypeObject BL_ActionActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject BL_ActionActuator::Parents[] = {
+ &BL_ActionActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef BL_ActionActuator::Methods[] = {
@@ -1061,24 +1065,37 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* BL_ActionActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* BL_ActionActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) {
+ py_setattro_up(SCA_IActuator);
+}
+
+
PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
- return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
+ return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
}
int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
- if (!PyUnicode_Check(value))
+ if (!PyString_Check(value))
{
PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action");
return PY_SET_ATTR_FAIL;
}
bAction *action= NULL;
- STR_String val = _PyUnicode_AsString(value);
+ STR_String val = PyString_AsString(value);
if (val != "")
{
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index e328ce126ca..422b16bb3ec 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -49,8 +49,9 @@ public:
short blendin,
short priority,
short end_reset,
- float stride)
- : SCA_IActuator(gameobj),
+ float stride,
+ PyTypeObject* T=&Type)
+ : SCA_IActuator(gameobj,T),
m_lastpos(0, 0, 0),
m_blendframe(0),
@@ -112,6 +113,10 @@ public:
KX_PYMETHOD_DOC(BL_ActionActuator,setChannel);
+ virtual PyObject* py_getattro(PyObject* attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject* attr, PyObject* value);
+
static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 177f261e40b..b907e300879 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -163,6 +163,7 @@ extern "C" {
#include "SG_BBox.h"
#include "SG_Tree.h"
+// defines USE_ODE to choose physics engine
#include "KX_ConvertPhysicsObject.h"
#ifdef USE_BULLET
#include "CcdPhysicsEnvironment.h"
@@ -1609,6 +1610,18 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
break;
#endif
+#ifdef USE_SUMO_SOLID
+ case UseSumo:
+ KX_ConvertSumoObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop);
+ break;
+#endif
+
+#ifdef USE_ODE
+ case UseODE:
+ KX_ConvertODEEngineObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop);
+ break;
+#endif //USE_ODE
+
case UseDynamo:
//KX_ConvertDynamoObject(gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop);
break;
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index 970539777f4..7aa8714de3a 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -427,17 +427,20 @@ PyTypeObject BL_ShapeActionActuator::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_IActuator::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject BL_ShapeActionActuator::Parents[] = {
+ &BL_ShapeActionActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
PyMethodDef BL_ShapeActionActuator::Methods[] = {
{"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc},
@@ -477,6 +480,19 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = {
{ NULL } //Sentinel
};
+
+PyObject* BL_ShapeActionActuator::py_getattro(PyObject* attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* BL_ShapeActionActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) {
+ py_setattro_up(SCA_IActuator);
+}
+
/* setStart */
const char BL_ShapeActionActuator::GetAction_doc[] =
"getAction()\n"
@@ -485,7 +501,7 @@ const char BL_ShapeActionActuator::GetAction_doc[] =
PyObject* BL_ShapeActionActuator::PyGetAction() {
ShowDeprecationWarning("getAction()", "the action property");
if (m_action){
- return PyUnicode_FromString(m_action->id.name+2);
+ return PyString_FromString(m_action->id.name+2);
}
Py_RETURN_NONE;
}
@@ -844,21 +860,21 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* args) {
PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
- return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
+ return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
}
int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
/* exact copy of BL_ActionActuator's function from here down */
- if (!PyUnicode_Check(value))
+ if (!PyString_Check(value))
{
PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action");
return PY_SET_ATTR_FAIL;
}
bAction *action= NULL;
- STR_String val = _PyUnicode_AsString(value);
+ STR_String val = PyString_AsString(value);
if (val != "")
{
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index 890fe3f9de9..d268eef6d23 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -50,8 +50,9 @@ public:
short playtype,
short blendin,
short priority,
- float stride)
- : SCA_IActuator(gameobj),
+ float stride,
+ PyTypeObject* T=&Type)
+ : SCA_IActuator(gameobj,T),
m_lastpos(0, 0, 0),
m_blendframe(0),
@@ -105,6 +106,10 @@ public:
KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType);
KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetType);
+ virtual PyObject* py_getattro(PyObject* attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject* attr, PyObject* value);
+
static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 9e0a710f44f..86e20b88580 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -44,12 +44,21 @@
#include "DummyPhysicsEnvironment.h"
+//to decide to use sumo/ode or dummy physics - defines USE_ODE
#include "KX_ConvertPhysicsObject.h"
#ifdef USE_BULLET
#include "CcdPhysicsEnvironment.h"
#endif
+#ifdef USE_ODE
+#include "OdePhysicsEnvironment.h"
+#endif //USE_ODE
+
+#ifdef USE_SUMO_SOLID
+#include "SumoPhysicsEnvironment.h"
+#endif
+
#include "KX_BlenderSceneConverter.h"
#include "KX_BlenderScalarInterpolator.h"
#include "BL_BlenderDataConversion.h"
@@ -136,6 +145,10 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
delete (*itm).second;
itm++;
}
+
+#ifdef USE_SUMO_SOLID
+ KX_ClearSumoSharedShapes();
+#endif
#ifdef USE_BULLET
KX_ClearBulletSharedShapes();
@@ -318,7 +331,20 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
break;
}
-#endif
+#endif
+
+#ifdef USE_SUMO_SOLID
+ case UseSumo:
+ destinationscene ->SetPhysicsEnvironment(new SumoPhysicsEnvironment());
+ break;
+#endif
+#ifdef USE_ODE
+
+ case UseODE:
+ destinationscene ->SetPhysicsEnvironment(new ODEPhysicsEnvironment());
+ break;
+#endif //USE_ODE
+
case UseDynamo:
{
}
diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile
index ed95aa968c7..abded70f289 100644
--- a/source/gameengine/Converter/Makefile
+++ b/source/gameengine/Converter/Makefile
@@ -39,7 +39,8 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_SOLID)/include
CPPFLAGS += -I$(NAN_BULLET2)/include
CPPFLAGS += -I../../blender
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index 05ea01c902a..3e0929e605a 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -21,6 +21,11 @@ incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu'
incs += ' #source/blender/windowmanager'
incs += ' #source/blender/makesrna'
+if env['WITH_BF_SOLID']:
+ incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include'
+ incs += ' ' + env['BF_SOLID_INC']
+ defs.append('USE_SUMO_SOLID')
+
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_BULLET_INC']
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
index 6779c2ea780..d90da8b3a92 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -29,6 +29,7 @@
const STR_String CBoolValue::sTrueString = "TRUE";
const STR_String CBoolValue::sFalseString = "FALSE";
+
CBoolValue::CBoolValue()
/*
pre: false
@@ -209,5 +210,5 @@ CValue* CBoolValue::GetReplica()
PyObject* CBoolValue::ConvertValueToPython()
{
- return PyBool_FromLong(m_bool != 0);
+ return PyInt_FromLong(m_bool != 0);
}
diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt
index dffd13f64ff..e3942b46557 100644
--- a/source/gameengine/Expressions/CMakeLists.txt
+++ b/source/gameengine/Expressions/CMakeLists.txt
@@ -32,7 +32,6 @@ SET(INC
../../../intern/string
../../../intern/moto/include
../../../source/gameengine/SceneGraph
- ../../../source/blender/blenloader
${PYTHON_INC}
)
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index b782de4bef6..227518e9439 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -330,7 +330,7 @@ void CIntValue::SetValue(CValue* newval)
PyObject* CIntValue::ConvertValueToPython()
{
if((m_int > INT_MIN) && (m_int < INT_MAX))
- return PyLong_FromSsize_t(m_int);
+ return PyInt_FromLong(m_int);
else
return PyLong_FromLongLong(m_int);
}
diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/KX_Python.h
index 61f7ef05042..b8006fdf0ed 100644
--- a/source/gameengine/Expressions/KX_Python.h
+++ b/source/gameengine/Expressions/KX_Python.h
@@ -32,8 +32,6 @@
//#define USE_DL_EXPORT
#include "Python.h"
-#define USE_MATHUTILS // Blender 2.5x api will use mathutils, for a while we might want to test without it
-
#ifdef __FreeBSD__
#include <osreldate.h>
#if __FreeBSD_version > 500039
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index 38b00dcc8fb..59344ddb7b7 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -76,9 +76,9 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
return NULL;
}
- if (PyUnicode_Check(pyindex))
+ if (PyString_Check(pyindex))
{
- CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(pyindex));
+ CValue *item = ((CListValue*) list)->FindValue(PyString_AsString(pyindex));
if (item) {
PyObject* pyobj = item->ConvertValueToPython();
if(pyobj)
@@ -87,14 +87,14 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
return item->GetProxy();
}
}
- else if (PyLong_Check(pyindex))
+ else if (PyInt_Check(pyindex))
{
- int index = PyLong_AsSsize_t(pyindex);
+ int index = PyInt_AsLong(pyindex);
return listvalue_buffer_item(self, index); /* wont add a ref */
}
PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */
- PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", _PyUnicode_AsString(pyindex_str));
+ PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str));
Py_DECREF(pyindex_str);
return NULL;
}
@@ -220,12 +220,12 @@ static int listvalue_buffer_contains(PyObject *self_v, PyObject *value)
return -1;
}
- if (PyUnicode_Check(value)) {
- if (self->FindValue((const char *)_PyUnicode_AsString(value))) {
+ if (PyString_Check(value)) {
+ if (self->FindValue((const char *)PyString_AsString(value))) {
return 1;
}
}
- else if (PyObject_TypeCheck(value, &CValue::Type)) { /* not dict like at all but this worked before __contains__ was used */
+ else if (BGE_PROXY_CHECK_TYPE(value)) { /* not dict like at all but this worked before __contains__ was used */
CValue *item= static_cast<CValue *>(BGE_PROXY_REF(value));
for (int i=0; i < self->GetCount(); i++)
if (self->GetValue(i) == item) // Com
@@ -289,19 +289,25 @@ PyTypeObject CListValue::Type = {
0, /*tp_hash*/
0, /*tp_call */
0,
- NULL,
- NULL,
+ py_base_getattro,
+ py_base_setattro,
0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ Py_TPFLAGS_DEFAULT,
0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject CListValue::Parents[] = {
+ &CListValue::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ NULL
};
+
+
+
PyMethodDef CListValue::Methods[] = {
/* List style access */
{"append", (PyCFunction)CListValue::sPyappend,METH_O},
@@ -323,12 +329,21 @@ PyAttributeDef CListValue::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* CListValue::py_getattro(PyObject* attr) {
+ py_getattro_up(CValue);
+}
+
+PyObject* CListValue::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
+
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-CListValue::CListValue()
-: CPropValue()
+CListValue::CListValue(PyTypeObject *T )
+: CPropValue(T)
{
m_bReleaseContents=true;
}
@@ -544,7 +559,7 @@ PyObject* CListValue::Pyindex(PyObject *value)
CValue* elem = GetValue(i);
if (checkobj==elem || CheckEqual(checkobj,elem))
{
- result = PyLong_FromSsize_t(i);
+ result = PyInt_FromLong(i);
break;
}
}
@@ -567,7 +582,7 @@ PyObject* CListValue::Pycount(PyObject* value)
if (checkobj==NULL) { /* in this case just return that there are no items in the list */
PyErr_Clear();
- return PyLong_FromSsize_t(0);
+ return PyInt_FromLong(0);
}
int numelem = GetCount();
@@ -581,7 +596,7 @@ PyObject* CListValue::Pycount(PyObject* value)
}
checkobj->Release();
- return PyLong_FromSsize_t(numfound);
+ return PyInt_FromLong(numfound);
}
/* Matches python dict.get(key, [default]) */
@@ -608,7 +623,7 @@ PyObject* CListValue::Pyget(PyObject *args)
/* Matches python dict.has_key() */
PyObject* CListValue::Pyhas_key(PyObject* value)
{
- if (PyUnicode_Check(value) && FindValue((const char *)_PyUnicode_AsString(value)))
+ if (PyString_Check(value) && FindValue((const char *)PyString_AsString(value)))
Py_RETURN_TRUE;
Py_RETURN_FALSE;
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index 98e6f216f11..68e900e25e0 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -24,7 +24,7 @@ class CListValue : public CPropValue
//PLUGIN_DECLARE_SERIAL (CListValue,CValue)
public:
- CListValue();
+ CListValue(PyTypeObject *T = &Type);
virtual ~CListValue();
void AddConfigurationData(CValue* menuvalue);
@@ -60,6 +60,8 @@ public:
bool CheckEqual(CValue* first,CValue* second);
+ virtual PyObject* py_getattro(PyObject* attr);
+ virtual PyObject* py_getattro_dict();
virtual PyObject* py_repr(void) {
PyObject *py_proxy= this->GetProxy();
PyObject *py_list= PySequence_List(py_proxy);
diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile
index 09512c3ae87..f46c0037200 100644
--- a/source/gameengine/Expressions/Makefile
+++ b/source/gameengine/Expressions/Makefile
@@ -37,7 +37,6 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
CPPFLAGS += -I../../blender/makesdna
-CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 475953749de..defb6853e67 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -74,13 +74,11 @@ PyTypeObject PyObjectPlus::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- NULL // no subtype
+ Methods
};
@@ -93,88 +91,6 @@ PyObjectPlus::~PyObjectPlus()
// assert(ob_refcnt==0);
}
-
-PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type.
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(self);
- if(self_plus==NULL) {
- PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
- return NULL;
- }
-
- return self_plus->py_repr();
-}
-
-
-PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyTypeObject *base_type;
- PyObjectPlus_Proxy *base = NULL;
-
- if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base))
- return NULL;
-
- /* the 'base' PyObject may be subclassed (multiple times even)
- * we need to find the first C++ defined class to check 'type'
- * is a subclass of the base arguments type.
- *
- * This way we can share one tp_new function for every PyObjectPlus
- *
- * eg.
- *
- * # CustomOb is called 'type' in this C code
- * class CustomOb(GameTypes.KX_GameObject):
- * pass
- *
- * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type
- * ob = CustomOb(cont.owner)
- *
- * */
- base_type= Py_TYPE(base);
- while(base_type && !BGE_PROXY_CHECK_TYPE(base_type))
- base_type= base_type->tp_base;
-
- if(base_type==NULL || !BGE_PROXY_CHECK_TYPE(base_type)) {
- PyErr_SetString(PyExc_TypeError, "can't subclass from a blender game type because the argument given is not a game class or subclass");
- return NULL;
- }
-
- /* use base_type rather then Py_TYPE(base) because we could alredy be subtyped */
- if(!PyType_IsSubtype(type, base_type)) {
- PyErr_Format(PyExc_TypeError, "can't subclass blender game type <%s> from <%s> because it is not a subclass", base_type->tp_name, type->tp_name);
- return NULL;
- }
-
- /* invalidate the existing base and return a new subclassed one,
- * this is a bit dodgy in that it also attaches its self to the existing object
- * which is not really 'correct' python OO but for our use its OK. */
-
- PyObjectPlus_Proxy *ret = (PyObjectPlus_Proxy *) type->tp_alloc(type, 0); /* starts with 1 ref, used for the return ref' */
- ret->ref= base->ref;
- base->ref= NULL; /* invalidate! disallow further access */
-
- ret->py_owns= base->py_owns;
-
- ret->ref->m_proxy= NULL;
-
- /* 'base' may be free'd after this func finished but not necessarily
- * there is no reference to the BGE data now so it will throw an error on access */
- Py_DECREF(base);
-
- ret->ref->m_proxy= (PyObject *)ret; /* no need to add a ref because one is added when creating. */
- Py_INCREF(ret); /* we return a new ref but m_proxy holds a ref so we need to add one */
-
-
- /* 'ret' will have 2 references.
- * - One ref is needed because ret->ref->m_proxy holds a refcount to the current proxy.
- * - Another is needed for returning the value.
- *
- * So we should be ok with 2 refs, but for some reason this crashes. so adding a new ref...
- * */
-
- return (PyObject *)ret;
-}
-
void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper
{
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
@@ -183,56 +99,143 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper
self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */
delete self_plus;
}
-
+
BGE_PROXY_REF(self)= NULL; // not really needed
}
-
-#if 0
- /* is ok normally but not for subtyping, use tp_free instead. */
PyObject_DEL( self );
-#else
- Py_TYPE(self)->tp_free(self);
-#endif
};
-PyObjectPlus::PyObjectPlus() : SG_QList() // constructor
+PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList() // constructor
{
+ MT_assert(T != NULL);
m_proxy= NULL;
};
-
+
/*------------------------------
* PyObjectPlus Methods -- Every class, even the abstract one should have a Methods
------------------------------*/
PyMethodDef PyObjectPlus::Methods[] = {
+ {"isA", (PyCFunction) sPyisA, METH_O},
{NULL, NULL} /* Sentinel */
};
-#define attr_invalid (&(PyObjectPlus::Attributes[0]))
PyAttributeDef PyObjectPlus::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid),
{NULL} //Sentinel
};
+PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ Py_RETURN_FALSE;
+}
+/*------------------------------
+ * PyObjectPlus Parents -- Every class, even the abstract one should have parents
+------------------------------*/
+PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL};
-PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+/*------------------------------
+ * PyObjectPlus attributes -- attributes
+------------------------------*/
+
+
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
{
- return PyBool_FromLong(self_v ? 1:0);
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
+ if(!strcmp("invalid", PyString_AsString(attr))) {
+ Py_RETURN_TRUE;
+ }
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ PyObject *ret= self_plus->py_getattro(attr);
+
+ /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
+ if(ret==NULL) {
+ char *attr_str= PyString_AsString(attr);
+
+ if (strcmp(attr_str, "__dict__")==0)
+ {
+ /* the error string will probably not
+ * be set but just incase clear it */
+ PyErr_Clear();
+ ret= self_plus->py_getattro_dict();
+ }
+ else if (!PyErr_Occurred()) {
+ /* We looked for an attribute but it wasnt found
+ * since py_getattro didnt set the error, set it here */
+ PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str);
+ }
+ }
+ return ret;
}
-/* note, this is called as a python 'getset, where the PyAttributeDef is the closure */
-PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef)
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value)
{
- void *self= (void *)(BGE_PROXY_REF(self_py));
- if(self==NULL) {
- if(attrdef == attr_invalid)
- Py_RETURN_TRUE; // dont bother running the function
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+ return -1;
+ }
+
+ if (value==NULL)
+ return self_plus->py_delattro(attr);
+
+ return self_plus->py_setattro(attr, value);
+}
+PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type.
+{
+
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return NULL;
}
+
+ return self_plus->py_repr();
+}
+PyObject *PyObjectPlus::py_getattro(PyObject* attr)
+{
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+ if (descr == NULL) {
+ return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
+ } else {
+ /* Copied from py_getattro_up */
+ if (PyCObject_Check(descr)) {
+ return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr));
+ } else if (descr->ob_type->tp_descr_get) {
+ return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy);
+ } else {
+ return NULL;
+ }
+ /* end py_getattro_up copy */
+ }
+}
+
+PyObject* PyObjectPlus::py_getattro_dict() {
+ return py_getattr_dict(NULL, Type.tp_dict);
+}
+int PyObjectPlus::py_delattro(PyObject* attr)
+{
+ PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted");
+ return 1;
+}
+
+int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value)
+{
+ PyErr_SetString(PyExc_AttributeError, "attribute cant be set");
+ return PY_SET_ATTR_MISSING;
+}
+
+PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef)
+{
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
{
// fake attribute, ignore
@@ -256,14 +259,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
{
bool *val = reinterpret_cast<bool*>(ptr);
ptr += sizeof(bool);
- PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val));
+ PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_SHORT:
{
short int *val = reinterpret_cast<short int*>(ptr);
ptr += sizeof(short int);
- PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val));
+ PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_ENUM:
@@ -278,7 +281,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
{
int *val = reinterpret_cast<int*>(ptr);
ptr += sizeof(int);
- PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val));
+ PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_FLOAT:
@@ -302,12 +305,12 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
case KX_PYATTRIBUTE_TYPE_BOOL:
{
bool *val = reinterpret_cast<bool*>(ptr);
- return PyLong_FromSsize_t(*val);
+ return PyInt_FromLong(*val);
}
case KX_PYATTRIBUTE_TYPE_SHORT:
{
short int *val = reinterpret_cast<short int*>(ptr);
- return PyLong_FromSsize_t(*val);
+ return PyInt_FromLong(*val);
}
case KX_PYATTRIBUTE_TYPE_ENUM:
// enum are like int, just make sure the field size is the same
@@ -319,7 +322,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
case KX_PYATTRIBUTE_TYPE_INT:
{
int *val = reinterpret_cast<int*>(ptr);
- return PyLong_FromSsize_t(*val);
+ return PyInt_FromLong(*val);
}
case KX_PYATTRIBUTE_TYPE_FLOAT:
{
@@ -328,23 +331,18 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
}
case KX_PYATTRIBUTE_TYPE_VECTOR:
{
- MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr);
-#ifdef USE_MATHUTILS
- float fval[3]= {(*val)[0], (*val)[1], (*val)[2]};
- return newVectorObject(fval, 3, Py_NEW);
-#else
PyObject* resultlist = PyList_New(3);
+ MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr);
for (unsigned int i=0; i<3; i++)
{
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
}
return resultlist;
-#endif
}
case KX_PYATTRIBUTE_TYPE_STRING:
{
STR_String *val = reinterpret_cast<STR_String*>(ptr);
- return PyUnicode_FromString(*val);
+ return PyString_FromString(*val);
}
default:
return NULL;
@@ -352,15 +350,8 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
}
}
-/* note, this is called as a python getset */
-int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef)
+int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value)
{
- void *self= (void *)(BGE_PROXY_REF(self_py));
- if(self==NULL) {
- PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
- return PY_SET_ATTR_FAIL;
- }
-
void *undoBuffer = NULL;
void *sourceBuffer = NULL;
size_t bufferSize = 0;
@@ -425,9 +416,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
{
bool *var = reinterpret_cast<bool*>(ptr);
ptr += sizeof(bool);
- if (PyLong_Check(item))
+ if (PyInt_Check(item))
{
- *var = (PyLong_AsSsize_t(item) != 0);
+ *var = (PyInt_AsLong(item) != 0);
}
else if (PyBool_Check(item))
{
@@ -444,9 +435,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
{
short int *var = reinterpret_cast<short int*>(ptr);
ptr += sizeof(short int);
- if (PyLong_Check(item))
+ if (PyInt_Check(item))
{
- long val = PyLong_AsSsize_t(item);
+ long val = PyInt_AsLong(item);
if (attrdef->m_clamp)
{
if (val < attrdef->m_imin)
@@ -480,9 +471,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
{
int *var = reinterpret_cast<int*>(ptr);
ptr += sizeof(int);
- if (PyLong_Check(item))
+ if (PyInt_Check(item))
{
- long val = PyLong_AsSsize_t(item);
+ long val = PyInt_AsLong(item);
if (attrdef->m_clamp)
{
if (val < attrdef->m_imin)
@@ -615,9 +606,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
case KX_PYATTRIBUTE_TYPE_BOOL:
{
bool *var = reinterpret_cast<bool*>(ptr);
- if (PyLong_Check(value))
+ if (PyInt_Check(value))
{
- *var = (PyLong_AsSsize_t(value) != 0);
+ *var = (PyInt_AsLong(value) != 0);
}
else if (PyBool_Check(value))
{
@@ -633,9 +624,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
case KX_PYATTRIBUTE_TYPE_SHORT:
{
short int *var = reinterpret_cast<short int*>(ptr);
- if (PyLong_Check(value))
+ if (PyInt_Check(value))
{
- long val = PyLong_AsSsize_t(value);
+ long val = PyInt_AsLong(value);
if (attrdef->m_clamp)
{
if (val < attrdef->m_imin)
@@ -668,9 +659,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
case KX_PYATTRIBUTE_TYPE_INT:
{
int *var = reinterpret_cast<int*>(ptr);
- if (PyLong_Check(value))
+ if (PyInt_Check(value))
{
- long val = PyLong_AsSsize_t(value);
+ long val = PyInt_AsLong(value);
if (attrdef->m_clamp)
{
if (val < attrdef->m_imin)
@@ -755,9 +746,9 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
case KX_PYATTRIBUTE_TYPE_STRING:
{
STR_String *var = reinterpret_cast<STR_String*>(ptr);
- if (PyUnicode_Check(value))
+ if (PyString_Check(value))
{
- char *val = _PyUnicode_AsString(value);
+ char *val = PyString_AsString(value);
if (attrdef->m_clamp)
{
if (strlen(val) < attrdef->m_imin)
@@ -838,6 +829,48 @@ PyObject *PyObjectPlus::py_repr(void)
return NULL;
}
+/*------------------------------
+ * PyObjectPlus isA -- the isA functions
+------------------------------*/
+bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename"
+{
+ int i;
+ PyParentObject P;
+ PyParentObject *Ps = GetParents();
+
+ for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+ if (P==T)
+ return true;
+
+ return false;
+}
+
+
+bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent
+{
+ int i;
+ PyParentObject P;
+ PyParentObject *Ps = GetParents();
+
+ for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+ if (strcmp(P->tp_name, mytypename)==0)
+ return true;
+
+ return false;
+}
+
+PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA
+{
+ if (PyType_Check(value)) {
+ return PyBool_FromLong(isA((PyTypeObject *)value));
+ } else if (PyString_Check(value)) {
+ return PyBool_FromLong(isA(PyString_AsString(value)));
+ }
+ PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string");
+ return NULL;
+}
+
+
void PyObjectPlus::ProcessReplica()
{
/* Clear the proxy, will be created again if needed with GetProxy()
@@ -862,6 +895,27 @@ void PyObjectPlus::InvalidateProxy() // check typename of each parent
}
}
+/* Utility function called by the macro py_getattro_up()
+ * for getting ob.__dict__() values from our PyObject
+ * this is used by python for doing dir() on an object, so its good
+ * if we return a list of attributes and methods.
+ *
+ * Other then making dir() useful the value returned from __dict__() is not useful
+ * since every value is a Py_None
+ * */
+PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict)
+{
+ if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */
+ PyErr_Clear();
+ pydict = PyDict_New();
+ }
+
+ PyDict_Update(pydict, tp_dict);
+ return pydict;
+}
+
+
+
PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp)
{
if (self->m_proxy==NULL)
@@ -932,7 +986,7 @@ void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* n
co_filename= PyObject_GetAttrString(f_code, "co_filename");
if (co_filename) {
- printf("\t%s:%d\n", _PyUnicode_AsString(co_filename), (int)PyLong_AsSsize_t(f_lineno));
+ printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
Py_DECREF(f_lineno);
Py_DECREF(f_code);
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index a18df9d36a9..c002dccefe4 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -45,15 +45,21 @@
* Python defines
------------------------------*/
-#ifdef USE_MATHUTILS
-extern "C" {
-#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */
-}
+
+
+#if PY_VERSION_HEX > 0x03000000
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromFormat PyUnicode_FromFormat
+#define PyString_Check PyUnicode_Check
+#define PyString_Size PyUnicode_GetSize
+
+#define PyInt_FromLong PyLong_FromSsize_t
+#define PyInt_AsLong PyLong_AsSsize_t
+#define PyString_AsString _PyUnicode_AsString
+#define PyInt_Check PyLong_Check
+#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one
#endif
-extern "C" {
-#include "../../blender/python/intern/bpy_compat.h"
-}
/*
@@ -135,7 +141,7 @@ typedef struct {
#define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns)
/* Note, sometimes we dont care what BGE type this is as long as its a proxy */
-#define BGE_PROXY_CHECK_TYPE(_type) ((_type)->tp_dealloc == PyObjectPlus::py_base_dealloc)
+#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyObjectPlus::py_base_dealloc)
// This must be the first line of each
@@ -145,10 +151,41 @@ typedef struct {
static PyTypeObject Type; \
static PyMethodDef Methods[]; \
static PyAttributeDef Attributes[]; \
+ static PyParentObject Parents[]; \
virtual PyTypeObject *GetType(void) {return &Type;}; \
+ virtual PyParentObject *GetParents(void) {return Parents;} \
virtual PyObject *GetProxy() {return GetProxy_Ext(this, &Type);}; \
virtual PyObject *NewProxy(bool py_owns) {return NewProxy_Ext(this, &Type, py_owns);}; \
+
+
+
+ // This defines the py_getattro_up macro
+ // which allows attribute and method calls
+ // to be properly passed up the hierarchy.
+ //
+ // Note, PyDict_GetItem() WONT set an exception!
+ // let the py_base_getattro function do this.
+
+#define py_getattro_up(Parent) \
+ \
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+ \
+ if(descr) { \
+ if (PyCObject_Check(descr)) { \
+ return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); \
+ } else if (descr->ob_type->tp_descr_get) { \
+ return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \
+ } else { \
+ return NULL; \
+ } \
+ } else { \
+ return Parent::py_getattro(attr); \
+ }
+
+#define py_getattro_dict_up(Parent) \
+ return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict);
+
/*
* nonzero values are an error for setattr
* however because of the nested lookups we need to know if the errors
@@ -160,6 +197,29 @@ typedef struct {
#define PY_SET_ATTR_MISSING -1
#define PY_SET_ATTR_SUCCESS 0
+#define py_setattro_up(Parent) \
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+ \
+ if(descr) { \
+ if (PyCObject_Check(descr)) { \
+ const PyAttributeDef* attrdef= reinterpret_cast<const PyAttributeDef *>(PyCObject_AsVoidPtr(descr)); \
+ if (attrdef->m_access == KX_PYATTRIBUTE_RO) { \
+ PyErr_Format(PyExc_AttributeError, "\"%s\" is read only", PyString_AsString(attr)); \
+ return PY_SET_ATTR_FAIL; \
+ } \
+ else { \
+ return py_set_attrdef((void *)this, attrdef, value); \
+ } \
+ } else { \
+ PyErr_Format(PyExc_AttributeError, "\"%s\" cannot be set", PyString_AsString(attr)); \
+ return PY_SET_ATTR_FAIL; \
+ } \
+ } else { \
+ PyErr_Clear(); \
+ return Parent::py_setattro(attr, value); \
+ }
+
+
/**
* These macros are helpfull when embedding Python routines. The second
* macro is one that also requires a documentation string
@@ -429,7 +489,7 @@ class PyObjectPlus : public SG_QList
Py_Header; // Always start with Py_Header
public:
- PyObjectPlus();
+ PyObjectPlus(PyTypeObject *T);
PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */
@@ -437,19 +497,30 @@ public:
/* These static functions are referenced by ALL PyObjectPlus_Proxy types
* they take the C++ reference from the PyObjectPlus_Proxy and call
- * its own virtual py_repr, py_base_dealloc ,etc. functions.
+ * its own virtual py_getattro, py_setattro etc. functions.
*/
-
- static PyObject* py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds); /* allows subclassing */
static void py_base_dealloc(PyObject *self);
+ static PyObject* py_base_getattro(PyObject * self, PyObject *attr);
+ static int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value);
static PyObject* py_base_repr(PyObject *self);
/* These are all virtual python methods that are defined in each class
* Our own fake subclassing calls these on each class, then calls the parent */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject *value);
virtual PyObject* py_repr(void);
- static PyObject* py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef);
- static int py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef);
+ static PyObject* py_get_attrdef(void *self, const PyAttributeDef *attrdef);
+ static int py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value);
+
+ /* isA() methods, shonky replacement for pythons issubclass()
+ * which we cant use because we have our own subclass system */
+ bool isA(PyTypeObject *T);
+ bool isA(const char *mytypename);
+
+ KX_PYMETHOD_O(PyObjectPlus,isA);
/* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */
static PyObject* pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
index c580e8fd23a..52f8a580f4d 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/StringValue.h
@@ -40,7 +40,7 @@ public:
virtual void SetValue(CValue* newval) { m_strString = newval->GetText(); SetModified(true); };
virtual CValue* GetReplica();
virtual PyObject* ConvertValueToPython() {
- return PyUnicode_FromString(m_strString.Ptr());
+ return PyString_FromString(m_strString.Ptr());
}
private:
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index d8c81f56f66..61dabff510b 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -54,17 +54,15 @@ PyTypeObject CValue::Type = {
py_base_repr,
0,
0,0,0,0,0,
- NULL,
- NULL,
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
- 0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
+};
+
+PyParentObject CValue::Parents[] = {
+ &CValue::Type,
+ NULL
};
PyMethodDef CValue::Methods[] = {
@@ -76,7 +74,7 @@ PyObject* CValue::PyGetName()
{
ShowDeprecationWarning("getName()", "the name property");
- return PyUnicode_FromString(this->GetName());
+ return PyString_FromString(this->GetName());
}
/*#define CVALUE_DEBUG*/
@@ -102,8 +100,8 @@ std::vector<SmartCValueRef> gRefList;
//int gRefCountValue;
#endif
-CValue::CValue()
- : PyObjectPlus(),
+CValue::CValue(PyTypeObject *T)
+ : PyObjectPlus(T),
#else
CValue::CValue()
:
@@ -555,9 +553,33 @@ PyAttributeDef CValue::Attributes[] = {
{ NULL } //Sentinel
};
+
+PyObject* CValue::py_getattro(PyObject *attr)
+{
+ char *attr_str= PyString_AsString(attr);
+ CValue* resultattr = GetProperty(attr_str);
+ if (resultattr)
+ {
+ /* only show the wanting here because python inspects for __class__ and KX_MeshProxy uses CValues name attr */
+ ShowDeprecationWarning("val = ob.attr", "val = ob['attr']");
+
+ PyObject* pyconvert = resultattr->ConvertValueToPython();
+
+ if (pyconvert)
+ return pyconvert;
+ else
+ return resultattr->GetProxy();
+ }
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* CValue::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) {
CValue * self = static_cast<CValue *> (self_v);
- return PyUnicode_FromString(self->GetName());
+ return PyString_FromString(self->GetName());
}
CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
@@ -601,23 +623,30 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
{
vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
} else
-#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(pyobj))
{
vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) );
} else
-#endif
if (PyLong_Check(pyobj))
{
vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
} else
- if (PyUnicode_Check(pyobj))
+ if (PyString_Check(pyobj))
{
- vallie = new CStringValue(_PyUnicode_AsString(pyobj),"");
+ vallie = new CStringValue(PyString_AsString(pyobj),"");
} else
- if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
+ if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
{
- vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
+ if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type))
+ {
+ vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
+ } else {
+
+ if(BGE_PROXY_REF(pyobj)) /* this is not a CValue */
+ PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix);
+ else /* PyObjectPlus_Proxy has been removed, cant use */
+ PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix);
+ }
} else
{
/* return an error value from the caller */
@@ -627,6 +656,57 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
}
+int CValue::py_delattro(PyObject *attr)
+{
+ ShowDeprecationWarning("del ob.attr", "del ob['attr']");
+
+ char *attr_str= PyString_AsString(attr);
+ if (RemoveProperty(attr_str))
+ return 0;
+
+ PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
+ return PY_SET_ATTR_MISSING;
+}
+
+int CValue::py_setattro(PyObject *attr, PyObject* pyobj)
+{
+ ShowDeprecationWarning("ob.attr = val", "ob['attr'] = val");
+
+ char *attr_str= PyString_AsString(attr);
+ CValue* oldprop = GetProperty(attr_str);
+ CValue* vallie;
+
+ /* Dissallow python to assign GameObjects, Scenes etc as values */
+ if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: ")))
+ {
+ if (oldprop)
+ oldprop->SetValue(vallie);
+ else
+ SetProperty(attr_str, vallie);
+
+ vallie->Release();
+ }
+ else {
+ // ConvertPythonToValue sets the error message
+ // must return missing so KX_GameObect knows this
+ // attribute was not a function or bult in attribute,
+ //
+ // CValue attributes override internal attributes
+ // so if it exists as a CValue attribute already,
+ // assume your trying to set it to a differnt CValue attribute
+ // otherwise return PY_SET_ATTR_MISSING so children
+ // classes know they can set it without conflict
+
+ if (GetProperty(attr_str))
+ return PY_SET_ATTR_COERCE_FAIL; /* failed to set an existing attribute */
+ else
+ return PY_SET_ATTR_MISSING; /* allow the KX_GameObject dict to set */
+ }
+
+ //PyObjectPlus::py_setattro(attr,value);
+ return PY_SET_ATTR_SUCCESS;
+};
+
PyObject* CValue::ConvertKeysToPython( void )
{
PyObject *pylist = PyList_New( 0 );
@@ -637,7 +717,7 @@ PyObject* CValue::ConvertKeysToPython( void )
std::map<STR_String,CValue*>::iterator it;
for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
- pystr = PyUnicode_FromString( (*it).first );
+ pystr = PyString_FromString( (*it).first );
PyList_Append(pylist, pystr);
Py_DECREF( pystr );
}
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index 8c9f99b335e..29ef19b46c9 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -215,18 +215,26 @@ public:
// Construction / Destruction
#ifndef NO_EXP_PYTHON_EMBEDDING
- CValue();
+ CValue(PyTypeObject *T = &Type);
//static PyObject* PyMake(PyObject*,PyObject*);
virtual PyObject *py_repr(void)
{
- return PyUnicode_FromString((const char*)GetText());
+ return PyString_FromString((const char*)GetText());
}
+
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
virtual PyObject* ConvertValueToPython() {
return NULL;
}
virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix);
+
+
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject* value);
static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
@@ -409,8 +417,8 @@ class CPropValue : public CValue
public:
#ifndef NO_EXP_PYTHON_EMBEDDING
- CPropValue() :
- CValue(),
+ CPropValue(PyTypeObject* T=&Type) :
+ CValue(T),
#else
CPropValue() :
#endif //NO_EXP_PYTHON_EMBEDDING
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
index 04d46e259d3..caed85b9938 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
@@ -42,8 +42,9 @@ SCA_2DFilterActuator::SCA_2DFilterActuator(
float float_arg,
int int_arg,
RAS_IRasterizer* rasterizer,
- RAS_IRenderTools* rendertools)
- : SCA_IActuator(gameobj),
+ RAS_IRenderTools* rendertools,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T),
m_type(type),
m_disableMotionBlur(flag),
m_float_arg(float_arg),
@@ -123,17 +124,23 @@ PyTypeObject SCA_2DFilterActuator::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_IActuator::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+
+PyParentObject SCA_2DFilterActuator::Parents[] = {
+ &SCA_2DFilterActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
PyMethodDef SCA_2DFilterActuator::Methods[] = {
/* add python functions to deal with m_msg... */
{NULL,NULL}
@@ -147,3 +154,18 @@ PyAttributeDef SCA_2DFilterActuator::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg),
{ NULL } //Sentinel
};
+
+PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* SCA_2DFilterActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
index c357c4f3e37..13b9997a010 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
@@ -56,12 +56,23 @@ public:
float float_arg,
int int_arg,
RAS_IRasterizer* rasterizer,
- RAS_IRenderTools* rendertools);
+ RAS_IRenderTools* rendertools,
+ PyTypeObject* T=&Type
+ );
void SetShaderText(const char *text);
virtual ~SCA_2DFilterActuator();
virtual bool Update();
virtual CValue* GetReplica();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
};
#endif
diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp
index 78e1350428e..87f7c612e7c 100644
--- a/source/gameengine/GameLogic/SCA_ANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_ANDController.cpp
@@ -42,9 +42,10 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj)
+SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_IController(gameobj)
+ SCA_IController(gameobj,T)
{
}
@@ -115,15 +116,19 @@ PyTypeObject SCA_ANDController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_ANDController::Parents[] = {
+ &SCA_ANDController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_ANDController::Methods[] = {
@@ -134,4 +139,12 @@ PyAttributeDef SCA_ANDController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_ANDController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_ANDController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h
index cb16d7fca01..9a359d57cb4 100644
--- a/source/gameengine/GameLogic/SCA_ANDController.h
+++ b/source/gameengine/GameLogic/SCA_ANDController.h
@@ -39,10 +39,18 @@ class SCA_ANDController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_ANDController(SCA_IObject* gameobj);
+ SCA_ANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
virtual ~SCA_ANDController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_ANDCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
index bdcc923e1d9..4dad65c5a25 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
@@ -40,8 +40,9 @@
SCA_ActuatorSensor::SCA_ActuatorSensor(SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
- const STR_String& actname)
- : SCA_ISensor(gameobj,eventmgr),
+ const STR_String& actname,
+ PyTypeObject* T )
+ : SCA_ISensor(gameobj,eventmgr,T),
m_checkactname(actname)
{
m_actuator = GetParent()->FindActuator(m_checkactname);
@@ -137,15 +138,19 @@ PyTypeObject SCA_ActuatorSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_ActuatorSensor::Parents[] = {
+ &SCA_ActuatorSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_ActuatorSensor::Methods[] = {
@@ -161,6 +166,18 @@ PyAttributeDef SCA_ActuatorSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_ActuatorSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_ISensor);
+}
+
int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*)
{
SCA_ActuatorSensor* sensor = reinterpret_cast<SCA_ActuatorSensor*>(self);
@@ -180,7 +197,7 @@ const char SCA_ActuatorSensor::GetActuator_doc[] =
PyObject* SCA_ActuatorSensor::PyGetActuator()
{
ShowDeprecationWarning("getActuator()", "the actuator property");
- return PyUnicode_FromString(m_checkactname);
+ return PyString_FromString(m_checkactname);
}
/* 4. setActuator */
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
index cf8e735cad4..6655e08dc70 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
@@ -46,7 +46,8 @@ class SCA_ActuatorSensor : public SCA_ISensor
public:
SCA_ActuatorSensor(class SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
- const STR_String& actname);
+ const STR_String& actname,
+ PyTypeObject* T=&Type );
virtual ~SCA_ActuatorSensor();
virtual CValue* GetReplica();
@@ -60,6 +61,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* 3. setProperty */
KX_PYMETHOD_DOC_VARARGS(SCA_ActuatorSensor,SetActuator);
/* 4. getProperty */
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
index ddb54c580b8..ff02680f191 100644
--- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
@@ -48,8 +48,9 @@
/* ------------------------------------------------------------------------- */
SCA_AlwaysSensor::SCA_AlwaysSensor(class SCA_EventManager* eventmgr,
- SCA_IObject* gameobj)
- : SCA_ISensor(gameobj,eventmgr)
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T)
{
//SetDrawColor(255,0,0);
Init();
@@ -120,15 +121,19 @@ PyTypeObject SCA_AlwaysSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_AlwaysSensor::Parents[] = {
+ &SCA_AlwaysSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_AlwaysSensor::Methods[] = {
@@ -139,4 +144,12 @@ PyAttributeDef SCA_AlwaysSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_AlwaysSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
index d58e05564d1..0f85a641ef1 100644
--- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
@@ -39,12 +39,22 @@ class SCA_AlwaysSensor : public SCA_ISensor
bool m_alwaysresult;
public:
SCA_AlwaysSensor(class SCA_EventManager* eventmgr,
- SCA_IObject* gameobj);
+ SCA_IObject* gameobj,
+ PyTypeObject* T =&Type);
virtual ~SCA_AlwaysSensor();
virtual CValue* GetReplica();
virtual bool Evaluate();
virtual bool IsPositiveTrigger();
virtual void Init();
+
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_ALWAYSSENSOR
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
index 11c6996a0a1..dcdae0b4e75 100644
--- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
@@ -51,8 +51,9 @@ SCA_DelaySensor::SCA_DelaySensor(class SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
int delay,
int duration,
- bool repeat)
- : SCA_ISensor(gameobj,eventmgr),
+ bool repeat,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
m_repeat(repeat),
m_delay(delay),
m_duration(duration)
@@ -146,15 +147,19 @@ PyTypeObject SCA_DelaySensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_DelaySensor::Parents[] = {
+ &SCA_DelaySensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_DelaySensor::Methods[] = {
@@ -178,6 +183,19 @@ PyAttributeDef SCA_DelaySensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_DelaySensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_ISensor);
+}
+
+
const char SCA_DelaySensor::SetDelay_doc[] =
"setDelay(delay)\n"
"\t- delay: length of the initial OFF period as number of frame\n"
@@ -244,7 +262,7 @@ const char SCA_DelaySensor::GetDelay_doc[] =
PyObject* SCA_DelaySensor::PyGetDelay()
{
ShowDeprecationWarning("getDelay()", "the delay property");
- return PyLong_FromSsize_t(m_delay);
+ return PyInt_FromLong(m_delay);
}
const char SCA_DelaySensor::GetDuration_doc[] =
@@ -253,7 +271,7 @@ const char SCA_DelaySensor::GetDuration_doc[] =
PyObject* SCA_DelaySensor::PyGetDuration()
{
ShowDeprecationWarning("getDuration()", "the duration property");
- return PyLong_FromSsize_t(m_duration);
+ return PyInt_FromLong(m_duration);
}
const char SCA_DelaySensor::GetRepeat_doc[] =
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h
index 8270e8959b7..5ccb33f8a16 100644
--- a/source/gameengine/GameLogic/SCA_DelaySensor.h
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.h
@@ -47,7 +47,8 @@ public:
SCA_IObject* gameobj,
int delay,
int duration,
- bool repeat);
+ bool repeat,
+ PyTypeObject* T =&Type);
virtual ~SCA_DelaySensor();
virtual CValue* GetReplica();
virtual bool Evaluate();
@@ -58,6 +59,10 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
/* setProperty */
KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetDelay);
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
index 60969300474..8e044b89c71 100644
--- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
@@ -46,8 +46,9 @@
/* ------------------------------------------------------------------------- */
SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj,
- const STR_String& exprtext)
- :SCA_IController(gameobj),
+ const STR_String& exprtext,
+ PyTypeObject* T)
+ :SCA_IController(gameobj,T),
m_exprText(exprtext),
m_exprCache(NULL)
{
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h
index 705f6dfc415..6a34d7b2dff 100644
--- a/source/gameengine/GameLogic/SCA_ExpressionController.h
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.h
@@ -42,7 +42,8 @@ class SCA_ExpressionController : public SCA_IController
public:
SCA_ExpressionController(SCA_IObject* gameobj,
- const STR_String& exprtext);
+ const STR_String& exprtext,
+ PyTypeObject* T=&Type );
virtual ~SCA_ExpressionController();
virtual CValue* GetReplica();
@@ -53,6 +54,14 @@ public:
* so that self references are removed before the controller itself is released
*/
virtual void Delete();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+// virtual PyObject* py_getattro(PyObject *attr);
+// virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_EXPRESSIONCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp
index 0fda75590c1..be7c2651686 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_IActuator.cpp
@@ -34,8 +34,9 @@
using namespace std;
-SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj) :
- SCA_ILogicBrick(gameobj),
+SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj,
+ PyTypeObject* T) :
+ SCA_ILogicBrick(gameobj,T),
m_links(0),
m_posevent(false),
m_negevent(false)
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
index 13c718ee837..27afcbc386b 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.h
+++ b/source/gameengine/GameLogic/SCA_IActuator.h
@@ -61,7 +61,8 @@ public:
* This class also inherits the default copy constructors
*/
- SCA_IActuator(SCA_IObject* gameobj);
+ SCA_IActuator(SCA_IObject* gameobj,
+ PyTypeObject* T =&Type);
/**
* UnlinkObject(...)
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index 7cbb728753a..f2c3c83a2d9 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -37,9 +37,10 @@
#include <config.h>
#endif
-SCA_IController::SCA_IController(SCA_IObject* gameobj)
+SCA_IController::SCA_IController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_ILogicBrick(gameobj),
+ SCA_ILogicBrick(gameobj,T),
m_statemask(0),
m_justActivated(false)
{
@@ -215,15 +216,17 @@ PyTypeObject SCA_IController::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_ILogicBrick::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
+};
+
+PyParentObject SCA_IController::Parents[] = {
+ &SCA_IController::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_IController::Methods[] = {
@@ -245,6 +248,22 @@ PyAttributeDef SCA_IController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_IController::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ILogicBrick);
+}
+
+PyObject* SCA_IController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ILogicBrick);
+}
+
+int SCA_IController::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ILogicBrick);
+}
+
+
+
PyObject* SCA_IController::PyGetActuators()
{
ShowDeprecationWarning("getActuators()", "the actuators property");
@@ -262,7 +281,7 @@ PyObject* SCA_IController::PyGetSensor(PyObject* value)
{
ShowDeprecationWarning("getSensor(string)", "the sensors[string] property");
- char *scriptArg = _PyUnicode_AsString(value);
+ char *scriptArg = PyString_AsString(value);
if (scriptArg==NULL) {
PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)");
return NULL;
@@ -286,7 +305,7 @@ PyObject* SCA_IController::PyGetActuator(PyObject* value)
{
ShowDeprecationWarning("getActuator(string)", "the actuators[string] property");
- char *scriptArg = _PyUnicode_AsString(value);
+ char *scriptArg = PyString_AsString(value);
if (scriptArg==NULL) {
PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)");
return NULL;
@@ -321,13 +340,13 @@ PyObject* SCA_IController::PyGetSensors()
PyObject* SCA_IController::PyGetState()
{
ShowDeprecationWarning("getState()", "the state property");
- return PyLong_FromSsize_t(m_statemask);
+ return PyInt_FromLong(m_statemask);
}
PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_IController* self= static_cast<SCA_IController*>(self_v);
- return PyLong_FromSsize_t(self->m_statemask);
+ return PyInt_FromLong(self->m_statemask);
}
PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h
index 523878bee26..a52c57ab3ed 100644
--- a/source/gameengine/GameLogic/SCA_IController.h
+++ b/source/gameengine/GameLogic/SCA_IController.h
@@ -47,7 +47,7 @@ protected:
bool m_justActivated;
bool m_bookmark;
public:
- SCA_IController(SCA_IObject* gameobj);
+ SCA_IController(SCA_IObject* gameobj,PyTypeObject* T);
virtual ~SCA_IController();
virtual void Trigger(class SCA_LogicManager* logicmgr)=0;
void LinkToSensor(SCA_ISensor* sensor);
@@ -98,6 +98,10 @@ public:
}
}
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
KX_PYMETHOD_NOARGS(SCA_IController,GetSensors);
KX_PYMETHOD_NOARGS(SCA_IController,GetActuators);
KX_PYMETHOD_O(SCA_IController,GetSensor);
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index ccb79a2d49f..2dc80f54568 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -35,9 +35,10 @@
SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL;
-SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj)
+SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- CValue(),
+ CValue(T),
m_gameobj(gameobj),
m_Execute_Priority(0),
m_Execute_Ueber_Priority(0),
@@ -193,17 +194,23 @@ PyTypeObject SCA_ILogicBrick::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject SCA_ILogicBrick::Parents[] = {
+ &SCA_ILogicBrick::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ NULL
};
+
+
PyMethodDef SCA_ILogicBrick::Methods[] = {
// --> Deprecated
{"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS},
@@ -238,6 +245,21 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef)
return 0;
}
+PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr)
+{
+ py_getattro_up(CValue);
+}
+
+PyObject* SCA_ILogicBrick::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
+
+int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(CValue);
+}
+
+
PyObject* SCA_ILogicBrick::PyGetOwner()
{
ShowDeprecationWarning("getOwner()", "the owner property");
@@ -274,7 +296,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args)
PyObject* SCA_ILogicBrick::PyGetExecutePriority()
{
ShowDeprecationWarning("getExecutePriority()", "the executePriority property");
- return PyLong_FromSsize_t(m_Execute_Priority);
+ return PyInt_FromLong(m_Execute_Priority);
}
@@ -304,5 +326,5 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg)
PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg)
{
- return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE);
+ return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE);
}
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h
index 50679856802..779e5397a6a 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.h
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h
@@ -53,7 +53,7 @@ protected:
CValue* GetEvent();
public:
- SCA_ILogicBrick(SCA_IObject* gameobj);
+ SCA_ILogicBrick(SCA_IObject* gameobj,PyTypeObject* T );
virtual ~SCA_ILogicBrick();
void SetExecutePriority(int execute_Priority);
@@ -121,6 +121,10 @@ public:
}
virtual bool LessComparedTo(SCA_ILogicBrick* other);
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
static class SCA_LogicManager* m_sCurrentLogicManager;
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index 6cd11f9e553..9876f2512c0 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -41,11 +41,8 @@
MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0);
SG_QList SCA_IObject::m_activeBookmarkedControllers;
-SCA_IObject::SCA_IObject():
- CValue(),
- m_initState(0),
- m_state(0),
- m_firstState(NULL)
+SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL)
+
{
m_suspended = false;
}
@@ -221,6 +218,51 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname)
}
+
+#if 0
+const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist)
+{
+ bool error = false;
+ m_sDummy = MT_Vector3(0,0,0);
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ int numelem = listval->GetCount();
+ if ( numelem <= 3)
+ {
+ int index;
+ for (index = 0;index<numelem;index++)
+ {
+ m_sDummy[index] = listval->GetValue(index)->GetNumber();
+ }
+ } else
+ {
+ error = true;
+ }
+
+ } else
+ {
+
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems <= 3)
+ {
+ int index;
+ for (index=0;index<numitems;index++)
+ {
+ m_sDummy[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index));
+ }
+ }
+ else
+ {
+ error = true;
+ }
+
+ }
+ return m_sDummy;
+}
+#endif
+
void SCA_IObject::Suspend()
{
if ((!m_ignore_activity_culling)
@@ -304,17 +346,23 @@ PyTypeObject SCA_IObject::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject SCA_IObject::Parents[] = {
+ &SCA_IObject::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ NULL
};
+
+
PyMethodDef SCA_IObject::Methods[] = {
//{"setOrientation", (PyCFunction) SCA_IObject::sPySetOrientation, METH_VARARGS},
//{"getOrientation", (PyCFunction) SCA_IObject::sPyGetOrientation, METH_VARARGS},
@@ -324,3 +372,12 @@ PyMethodDef SCA_IObject::Methods[] = {
PyAttributeDef SCA_IObject::Attributes[] = {
{ NULL } //Sentinel
};
+
+
+PyObject* SCA_IObject::py_getattro(PyObject *attr) {
+ py_getattro_up(CValue);
+}
+
+PyObject* SCA_IObject::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 3060410dc6b..eae427741ca 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -105,7 +105,7 @@ protected:
public:
- SCA_IObject();
+ SCA_IObject(PyTypeObject* T=&Type);
virtual ~SCA_IObject();
SCA_ControllerList& GetControllers()
@@ -199,12 +199,15 @@ public:
unsigned int GetState(void) { return m_state; }
// const class MT_Point3& ConvertPythonPylist(PyObject* pylist);
+
+ // here come the python forwarded methods
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
virtual int GetGameObjectType() {return -1;}
typedef enum ObjectTypes {
OBJ_ARMATURE=0,
- OBJ_CAMERA=1,
}ObjectTypes;
};
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index 4c1e0bd01c4..2783bf14600 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -50,8 +50,9 @@ void SCA_ISensor::ReParent(SCA_IObject* parent)
SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
- class SCA_EventManager* eventmgr) :
- SCA_ILogicBrick(gameobj)
+ class SCA_EventManager* eventmgr,
+ PyTypeObject* T ) :
+ SCA_ILogicBrick(gameobj,T)
{
m_links = 0;
m_suspended = false;
@@ -300,7 +301,7 @@ PyObject* SCA_ISensor::PyIsPositive()
{
ShowDeprecationWarning("isPositive()", "the read-only positive property");
int retval = GetState();
- return PyLong_FromSsize_t(retval);
+ return PyInt_FromLong(retval);
}
const char SCA_ISensor::IsTriggered_doc[] =
@@ -313,7 +314,7 @@ PyObject* SCA_ISensor::PyIsTriggered()
int retval = 0;
if (SCA_PythonController::m_sCurrentController)
retval = SCA_PythonController::m_sCurrentController->IsTriggered(this);
- return PyLong_FromSsize_t(retval);
+ return PyInt_FromLong(retval);
}
/**
@@ -354,7 +355,7 @@ const char SCA_ISensor::GetFrequency_doc[] =
PyObject* SCA_ISensor::PyGetFrequency()
{
ShowDeprecationWarning("getFrequency()", "the frequency property");
- return PyLong_FromSsize_t(m_pulse_frequency);
+ return PyInt_FromLong(m_pulse_frequency);
}
/**
@@ -488,17 +489,19 @@ PyTypeObject SCA_ISensor::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_ILogicBrick::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject SCA_ISensor::Parents[] = {
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
PyMethodDef SCA_ISensor::Methods[] = {
//Deprecated functions ----->
{"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive,
@@ -545,6 +548,19 @@ PyAttributeDef SCA_ISensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_ISensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ILogicBrick);
+}
+
+PyObject* SCA_ISensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ILogicBrick);
+}
+
+int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ILogicBrick);
+}
PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -552,13 +568,13 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D
int retval = 0;
if (SCA_PythonController::m_sCurrentController)
retval = SCA_PythonController::m_sCurrentController->IsTriggered(self);
- return PyLong_FromSsize_t(retval);
+ return PyInt_FromLong(retval);
}
PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
- return PyLong_FromSsize_t(self->GetState());
+ return PyInt_FromLong(self->GetState());
}
int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index 81864ab6a34..9bbd6ed41e4 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -101,7 +101,8 @@ public:
};
SCA_ISensor(SCA_IObject* gameobj,
- class SCA_EventManager* eventmgr);;
+ class SCA_EventManager* eventmgr,
+ PyTypeObject* T );;
~SCA_ISensor();
virtual void ReParent(SCA_IObject* parent);
@@ -172,6 +173,10 @@ public:
{ return !m_links; }
/* Python functions: */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
//Deprecated functions ----->
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive);
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
index f55921e648b..336529667d7 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
@@ -46,8 +46,9 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
short int joymode,
int axis, int axisf,int prec,
int button,
- int hat, int hatf, bool allevents)
- :SCA_ISensor(gameobj,eventmgr),
+ int hat, int hatf, bool allevents,
+ PyTypeObject* T )
+ :SCA_ISensor(gameobj,eventmgr,T),
m_pJoystickMgr(eventmgr),
m_axis(axis),
m_axisf(axisf),
@@ -268,17 +269,23 @@ PyTypeObject SCA_JoystickSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+PyParentObject SCA_JoystickSensor::Parents[] = {
+ &SCA_JoystickSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
PyMethodDef SCA_JoystickSensor::Methods[] = {
//Deprecated functions ------>
{"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc},
@@ -321,6 +328,20 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_JoystickSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ISensor);
+}
+
/* get index ---------------------------------------------------------- */
const char SCA_JoystickSensor::GetIndex_doc[] =
@@ -328,7 +349,7 @@ const char SCA_JoystickSensor::GetIndex_doc[] =
"\tReturns the joystick index to use.\n";
PyObject* SCA_JoystickSensor::PyGetIndex( ) {
ShowDeprecationWarning("getIndex()", "the index property");
- return PyLong_FromSsize_t(m_joyindex);
+ return PyInt_FromLong(m_joyindex);
}
@@ -338,7 +359,7 @@ const char SCA_JoystickSensor::SetIndex_doc[] =
"\tSets the joystick index to use.\n";
PyObject* SCA_JoystickSensor::PySetIndex( PyObject* value ) {
ShowDeprecationWarning("setIndex()", "the index property");
- int index = PyLong_AsSsize_t( value ); /* -1 on error, will raise an error in this case */
+ int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */
if (index < 0 || index >= JOYINDEX_MAX) {
PyErr_SetString(PyExc_ValueError, "joystick index out of range or not an int");
return NULL;
@@ -389,7 +410,7 @@ PyObject* SCA_JoystickSensor::PyGetAxisValue( ) {
PyObject *list= PyList_New(axis_index);
while(axis_index--) {
- PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index)));
+ PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index)));
}
return list;
@@ -402,7 +423,7 @@ const char SCA_JoystickSensor::GetThreshold_doc[] =
"\tReturns the threshold of the axis.\n";
PyObject* SCA_JoystickSensor::PyGetThreshold( ) {
ShowDeprecationWarning("getThreshold()", "the threshold property");
- return PyLong_FromSsize_t(m_precision);
+ return PyInt_FromLong(m_precision);
}
@@ -426,7 +447,7 @@ const char SCA_JoystickSensor::GetButton_doc[] =
"\tReturns the current button this sensor is checking.\n";
PyObject* SCA_JoystickSensor::PyGetButton( ) {
ShowDeprecationWarning("getButton()", "the button property");
- return PyLong_FromSsize_t(m_button);
+ return PyInt_FromLong(m_button);
}
/* set button -------------------------------------------------------- */
@@ -435,7 +456,7 @@ const char SCA_JoystickSensor::SetButton_doc[] =
"\tSets the button the sensor reacts to.\n";
PyObject* SCA_JoystickSensor::PySetButton( PyObject* value ) {
ShowDeprecationWarning("setButton()", "the button property");
- int button = PyLong_AsSsize_t(value);
+ int button = PyInt_AsLong(value);
if(button==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "expected an int");
return NULL;
@@ -466,7 +487,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) {
if(joy) {
for (i=0; i < joy->GetNumberOfButtons(); i++) {
if (joy->aButtonPressIsPositive(i)) {
- value = PyLong_FromSsize_t(i);
+ value = PyInt_FromLong(i);
PyList_Append(ls, value);
Py_DECREF(value);
}
@@ -528,7 +549,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfAxes( ) {
ShowDeprecationWarning("getNumAxes()", "the numAxis property");
SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
// when the joystick is null their is 0 exis still. dumb but scripters should use isConnected()
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 );
}
@@ -538,7 +559,7 @@ const char SCA_JoystickSensor::NumberOfButtons_doc[] =
PyObject* SCA_JoystickSensor::PyNumberOfButtons( ) {
ShowDeprecationWarning("getNumButtons()", "the numButtons property");
SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
}
@@ -548,7 +569,7 @@ const char SCA_JoystickSensor::NumberOfHats_doc[] =
PyObject* SCA_JoystickSensor::PyNumberOfHats( ) {
ShowDeprecationWarning("getNumHats()", "the numHats property");
SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
}
const char SCA_JoystickSensor::Connected_doc[] =
@@ -570,7 +591,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT
PyObject *list= PyList_New(axis_index);
while(axis_index--) {
- PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index)));
+ PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index)));
}
return list;
@@ -586,7 +607,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT
return NULL;
}
- return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1));
+ return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1));
}
PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -598,7 +619,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT
PyObject *list= PyList_New(hat_index);
while(hat_index--) {
- PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index)));
+ PyList_SET_ITEM(list, hat_index, PyInt_FromLong(joy->GetHat(hat_index)));
}
return list;
@@ -609,28 +630,28 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
- return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1));
+ return PyInt_FromLong(joy->GetHat(self->m_hat-1));
}
PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 );
}
PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
}
PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
- return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 );
+ return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
}
PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h
index 32f8ce567d2..e6a1d2eef32 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.h
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h
@@ -106,7 +106,8 @@ public:
short int joymode,
int axis, int axisf,int prec,
int button,
- int hat, int hatf, bool allevents);
+ int hat, int hatf, bool allevents,
+ PyTypeObject* T=&Type );
virtual ~SCA_JoystickSensor();
virtual CValue* GetReplica();
@@ -122,6 +123,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* Joystick Index */
KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex);
KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex);
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index 999e34dfa36..f8ee8ed8b41 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -48,8 +48,9 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
bool bAllKeys,
const STR_String& targetProp,
const STR_String& toggleProp,
- SCA_IObject* gameobj)
- :SCA_ISensor(gameobj,keybdmgr),
+ SCA_IObject* gameobj,
+ PyTypeObject* T )
+ :SCA_ISensor(gameobj,keybdmgr,T),
m_pKeyboardMgr(keybdmgr),
m_hotkey(hotkey),
m_qual(qual),
@@ -417,7 +418,7 @@ const char SCA_KeyboardSensor::GetKey_doc[] =
PyObject* SCA_KeyboardSensor::PyGetKey()
{
ShowDeprecationWarning("getKey()", "the key property");
- return PyLong_FromSsize_t(m_hotkey);
+ return PyInt_FromLong(m_hotkey);
}
/** 2. SetKey: change the key to look at */
@@ -449,7 +450,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] =
PyObject* SCA_KeyboardSensor::PyGetHold1()
{
ShowDeprecationWarning("getHold1()", "the hold1 property");
- return PyLong_FromSsize_t(m_qual);
+ return PyInt_FromLong(m_qual);
}
/** 4. SetHold1: change the first bucky bit */
@@ -481,7 +482,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] =
PyObject* SCA_KeyboardSensor::PyGetHold2()
{
ShowDeprecationWarning("getHold2()", "the hold2 property");
- return PyLong_FromSsize_t(m_qual2);
+ return PyInt_FromLong(m_qual2);
}
/** 6. SetHold2: change the second bucky bit */
@@ -531,8 +532,8 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys()
|| (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED))
{
PyObject* keypair = PyList_New(2);
- PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
- PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
+ PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+ PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
PyList_SET_ITEM(resultlist,index,keypair);
index++;
@@ -571,8 +572,8 @@ PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys()
|| (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED))
{
PyObject* keypair = PyList_New(2);
- PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
- PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
+ PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+ PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
PyList_SET_ITEM(resultlist,index,keypair);
index++;
@@ -591,12 +592,12 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
"getKeyStatus(keycode)\n"
"\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
{
- if (!PyLong_Check(value)) {
+ if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int");
return NULL;
}
- int keycode = PyLong_AsSsize_t(value);
+ int keycode = PyInt_AsLong(value);
if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
|| (keycode > SCA_IInputDevice::KX_ENDKEY)){
@@ -606,7 +607,7 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
- return PyLong_FromSsize_t(inevent.m_status);
+ return PyInt_FromLong(inevent.m_status);
}
/* ------------------------------------------------------------------------- */
@@ -630,15 +631,19 @@ PyTypeObject SCA_KeyboardSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_KeyboardSensor::Parents[] = {
+ &SCA_KeyboardSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_KeyboardSensor::Methods[] = {
@@ -667,6 +672,20 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_KeyboardSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ISensor);
+}
+
PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -682,8 +701,8 @@ PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU
if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
{
PyObject* keypair = PyList_New(2);
- PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
- PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
+ PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+ PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
PyList_Append(resultlist,keypair);
}
}
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
index 3185b386d41..033225cd9be 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
@@ -94,7 +94,8 @@ public:
bool bAllKeys,
const STR_String& targetProp,
const STR_String& toggleProp,
- SCA_IObject* gameobj);
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
virtual ~SCA_KeyboardSensor();
virtual CValue* GetReplica();
virtual void Init();
@@ -109,6 +110,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
//Deprecated functions ----->
/** 1. GetKey : check which key this sensor looks at */
KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetKey);
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index b782c6dfb93..83271288154 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -307,7 +307,6 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I
controller->Activate(m_triggeredControllerSet);
// so that the controller knows which sensor has activited it
// only needed for python controller
- // Note that this is safe even if the controller is subclassed.
if (controller->GetType() == &SCA_PythonController::Type)
{
SCA_PythonController* pythonController = (SCA_PythonController*)controller;
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
index 49fa19dce38..c5e1c3c0441 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -49,8 +49,9 @@
SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr,
int startx,int starty,
short int mousemode,
- SCA_IObject* gameobj)
- : SCA_ISensor(gameobj,eventmgr),
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
m_pMouseMgr(eventmgr),
m_x(startx),
m_y(starty)
@@ -253,7 +254,7 @@ const char SCA_MouseSensor::GetXPosition_doc[] =
"\tpixels\n";
PyObject* SCA_MouseSensor::PyGetXPosition() {
ShowDeprecationWarning("getXPosition()", "the position property");
- return PyLong_FromSsize_t(m_x);
+ return PyInt_FromLong(m_x);
}
/* get y position ---------------------------------------------------------- */
@@ -264,7 +265,7 @@ const char SCA_MouseSensor::GetYPosition_doc[] =
"\tpixels\n";
PyObject* SCA_MouseSensor::PyGetYPosition() {
ShowDeprecationWarning("getYPosition()", "the position property");
- return PyLong_FromSsize_t(m_y);
+ return PyInt_FromLong(m_y);
}
//<----- Deprecated
@@ -272,9 +273,9 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus,
"getButtonStatus(button)\n"
"\tGet the given button's status (KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED).\n")
{
- if (PyLong_Check(value))
+ if (PyInt_Check(value))
{
- int button = PyLong_AsSsize_t(value);
+ int button = PyInt_AsLong(value);
if ((button < SCA_IInputDevice::KX_LEFTMOUSE)
|| (button > SCA_IInputDevice::KX_RIGHTMOUSE)){
@@ -284,7 +285,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus,
SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice();
const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button);
- return PyLong_FromSsize_t(event.m_status);
+ return PyInt_FromLong(event.m_status);
}
Py_RETURN_NONE;
@@ -311,15 +312,19 @@ PyTypeObject SCA_MouseSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_MouseSensor::Parents[] = {
+ &SCA_MouseSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_MouseSensor::Methods[] = {
@@ -337,4 +342,18 @@ PyAttributeDef SCA_MouseSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_MouseSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_MouseSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ISensor);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h
index 47f0378bf69..6d6302b514a 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.h
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.h
@@ -92,7 +92,8 @@ class SCA_MouseSensor : public SCA_ISensor
SCA_MouseSensor(class SCA_MouseManager* keybdmgr,
int startx,int starty,
short int mousemode,
- SCA_IObject* gameobj);
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
virtual ~SCA_MouseSensor();
virtual CValue* GetReplica();
@@ -108,6 +109,10 @@ class SCA_MouseSensor : public SCA_ISensor
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
//Deprecated functions ----->
/* read x-coordinate */
KX_PYMETHOD_DOC_NOARGS(SCA_MouseSensor,GetXPosition);
diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp
index c00e5d6e617..d27aea5e6f7 100644
--- a/source/gameengine/GameLogic/SCA_NANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_NANDController.cpp
@@ -42,9 +42,10 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj)
+SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_IController(gameobj)
+ SCA_IController(gameobj,T)
{
}
@@ -115,15 +116,19 @@ PyTypeObject SCA_NANDController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_NANDController::Parents[] = {
+ &SCA_NANDController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_NANDController::Methods[] = {
@@ -134,4 +139,12 @@ PyAttributeDef SCA_NANDController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_NANDController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_NANDController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h
index 36a145e5f2b..0ae0ff19745 100644
--- a/source/gameengine/GameLogic/SCA_NANDController.h
+++ b/source/gameengine/GameLogic/SCA_NANDController.h
@@ -39,7 +39,7 @@ class SCA_NANDController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_NANDController(SCA_IObject* gameobj);
+ SCA_NANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
virtual ~SCA_NANDController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
@@ -47,6 +47,10 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_NANDCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp
index 9762d44fd5d..6c9141636b2 100644
--- a/source/gameengine/GameLogic/SCA_NORController.cpp
+++ b/source/gameengine/GameLogic/SCA_NORController.cpp
@@ -42,9 +42,10 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_NORController::SCA_NORController(SCA_IObject* gameobj)
+SCA_NORController::SCA_NORController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_IController(gameobj)
+ SCA_IController(gameobj,T)
{
}
@@ -115,15 +116,19 @@ PyTypeObject SCA_NORController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_NORController::Parents[] = {
+ &SCA_NORController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_NORController::Methods[] = {
@@ -134,4 +139,12 @@ PyAttributeDef SCA_NORController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_NORController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_NORController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h
index b96232375d6..06cbb70a489 100644
--- a/source/gameengine/GameLogic/SCA_NORController.h
+++ b/source/gameengine/GameLogic/SCA_NORController.h
@@ -39,10 +39,18 @@ class SCA_NORController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_NORController(SCA_IObject* gameobj);
+ SCA_NORController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
virtual ~SCA_NORController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_NORCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp
index a526dd8353c..42c0a67d657 100644
--- a/source/gameengine/GameLogic/SCA_ORController.cpp
+++ b/source/gameengine/GameLogic/SCA_ORController.cpp
@@ -42,8 +42,9 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_ORController::SCA_ORController(SCA_IObject* gameobj)
- :SCA_IController(gameobj)
+SCA_ORController::SCA_ORController(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ :SCA_IController(gameobj, T)
{
}
@@ -109,15 +110,19 @@ PyTypeObject SCA_ORController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_ORController::Parents[] = {
+ &SCA_ORController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_ORController::Methods[] = {
@@ -128,4 +133,13 @@ PyAttributeDef SCA_ORController::Attributes[] = {
{ NULL } //Sentinel
};
+
+PyObject* SCA_ORController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_ORController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h
index 09d31a85190..66f772c739e 100644
--- a/source/gameengine/GameLogic/SCA_ORController.h
+++ b/source/gameengine/GameLogic/SCA_ORController.h
@@ -39,11 +39,18 @@ class SCA_ORController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_ORController(SCA_IObject* gameobj);
+ SCA_ORController(SCA_IObject* gameobj, PyTypeObject* T=&Type);
virtual ~SCA_ORController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
};
#endif //__KX_ORCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index 215e30eceaf..4faa4b55d4a 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -42,8 +42,8 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype)
- : SCA_IActuator(gameobj),
+SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T )
+ : SCA_IActuator(gameobj,T),
m_type(acttype),
m_propname(propname),
m_exprtxt(expr),
@@ -244,15 +244,19 @@ PyTypeObject SCA_PropertyActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_PropertyActuator::Parents[] = {
+ &SCA_PropertyActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_PropertyActuator::Methods[] = {
@@ -272,6 +276,18 @@ PyAttributeDef SCA_PropertyActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* SCA_PropertyActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_IActuator);
+}
+
/* 1. setProperty */
const char SCA_PropertyActuator::SetProperty_doc[] =
"setProperty(name)\n"
@@ -306,7 +322,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] =
PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds)
{
ShowDeprecationWarning("getProperty()", "the 'propName' property");
- return PyUnicode_FromString(m_propname);
+ return PyString_FromString(m_propname);
}
/* 3. setValue */
@@ -336,7 +352,7 @@ const char SCA_PropertyActuator::GetValue_doc[] =
PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds)
{
ShowDeprecationWarning("getValue()", "the value property");
- return PyUnicode_FromString(m_exprtxt);
+ return PyString_FromString(m_exprtxt);
}
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h
index 8fb2e7a7bc5..a8df08dfc6e 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.h
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h
@@ -64,7 +64,9 @@ public:
SCA_IObject* sourceObj,
const STR_String& propname,
const STR_String& expr,
- int acttype);
+ int acttype,
+ PyTypeObject* T=&Type
+ );
~SCA_PropertyActuator();
@@ -84,6 +86,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// python wrapped methods
KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty);
KX_PYMETHOD_DOC(SCA_PropertyActuator,GetProperty);
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index 6d2e1a0aca5..3b343af3cba 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -48,8 +48,9 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
const STR_String& propname,
const STR_String& propval,
const STR_String& propmaxval,
- KX_PROPSENSOR_TYPE checktype)
- : SCA_ISensor(gameobj,eventmgr),
+ KX_PROPSENSOR_TYPE checktype,
+ PyTypeObject* T )
+ : SCA_ISensor(gameobj,eventmgr,T),
m_checktype(checktype),
m_checkpropval(propval),
m_checkpropmaxval(propmaxval),
@@ -318,15 +319,19 @@ PyTypeObject SCA_PropertySensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_PropertySensor::Parents[] = {
+ &SCA_PropertySensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_PropertySensor::Methods[] = {
@@ -348,6 +353,19 @@ PyAttributeDef SCA_PropertySensor::Attributes[] = {
{ NULL } //Sentinel
};
+
+PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_PropertySensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_ISensor);
+}
+
/* 1. getType */
const char SCA_PropertySensor::GetType_doc[] =
"getType()\n"
@@ -355,7 +373,7 @@ const char SCA_PropertySensor::GetType_doc[] =
PyObject* SCA_PropertySensor::PyGetType()
{
ShowDeprecationWarning("getType()", "the mode property");
- return PyLong_FromSsize_t(m_checktype);
+ return PyInt_FromLong(m_checktype);
}
/* 2. setType */
@@ -389,7 +407,7 @@ const char SCA_PropertySensor::GetProperty_doc[] =
PyObject* SCA_PropertySensor::PyGetProperty()
{
ShowDeprecationWarning("getProperty()", "the 'propName' property");
- return PyUnicode_FromString(m_checkpropname);
+ return PyString_FromString(m_checkpropname);
}
/* 4. setProperty */
@@ -426,7 +444,7 @@ const char SCA_PropertySensor::GetValue_doc[] =
PyObject* SCA_PropertySensor::PyGetValue()
{
ShowDeprecationWarning("getValue()", "the value property");
- return PyUnicode_FromString(m_checkpropval);
+ return PyString_FromString(m_checkpropval);
}
/* 6. setValue */
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h
index 3513fcdf5ae..538ecd65949 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.h
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.h
@@ -67,7 +67,8 @@ public:
const STR_String& propname,
const STR_String& propval,
const STR_String& propmaxval,
- KX_PROPSENSOR_TYPE checktype);
+ KX_PROPSENSOR_TYPE checktype,
+ PyTypeObject* T=&Type );
/**
* For property sensor, it is used to release the pre-calculated expression
@@ -88,6 +89,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* 1. getType */
KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetType);
/* 2. setType */
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index ffd95f00699..80e4f54c9c5 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -47,8 +47,10 @@
SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL;
-SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, int mode)
- : SCA_IController(gameobj),
+SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj,
+ int mode,
+ PyTypeObject* T)
+ : SCA_IController(gameobj, T),
m_bytecode(NULL),
m_function(NULL),
m_function_argc(0),
@@ -148,7 +150,7 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary)
/* Without __file__ set the sys.argv[0] is used for the filename
* which ends up with lines from the blender binary being printed in the console */
- PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_FromString(m_scriptName.Ptr()));
+ PyDict_SetItemString(m_pythondictionary, "__file__", PyString_FromString(m_scriptName.Ptr()));
}
@@ -178,16 +180,16 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
std::vector<SCA_IActuator*> lacts = m_sCurrentController->GetLinkedActuators();
std::vector<SCA_IActuator*>::iterator it;
- if (PyUnicode_Check(value)) {
+ if (PyString_Check(value)) {
/* get the actuator from the name */
- char *name= _PyUnicode_AsString(value);
+ char *name= PyString_AsString(value);
for(it = lacts.begin(); it!= lacts.end(); ++it) {
if( name == (*it)->GetName() ) {
return *it;
}
}
}
- else if (PyObject_TypeCheck(value, &SCA_IActuator::Type)) {
+ else if (BGE_PROXY_CHECK_TYPE(value)) {
PyObjectPlus *value_plus= BGE_PROXY_REF(value);
for(it = lacts.begin(); it!= lacts.end(); ++it) {
if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) {
@@ -198,7 +200,7 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
/* set the exception */
PyObject *value_str = PyObject_Repr(value); /* new ref */
- PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", _PyUnicode_AsString(value_str));
+ PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", PyString_AsString(value_str));
Py_DECREF(value_str);
return false;
@@ -243,17 +245,19 @@ PyTypeObject SCA_PythonController::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_IController::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject SCA_PythonController::Parents[] = {
+ &SCA_PythonController::Type,
+ &SCA_IController::Type,
+ &CValue::Type,
+ NULL
+};
PyMethodDef SCA_PythonController::Methods[] = {
{"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O},
{"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O},
@@ -486,6 +490,22 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
m_sCurrentController = NULL;
}
+
+
+PyObject* SCA_PythonController::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_PythonController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
+int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IController);
+}
+
PyObject* SCA_PythonController::PyActivate(PyObject *value)
{
if(m_sCurrentController != this) {
@@ -520,13 +540,13 @@ PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
PyObject* SCA_PythonController::PyGetScript()
{
ShowDeprecationWarning("getScript()", "the script property");
- return PyUnicode_FromString(m_scriptText);
+ return PyString_FromString(m_scriptText);
}
/* 2. setScript */
PyObject* SCA_PythonController::PySetScript(PyObject* value)
{
- char *scriptArg = _PyUnicode_AsString(value);
+ char *scriptArg = PyString_AsString(value);
ShowDeprecationWarning("setScript()", "the script property");
@@ -545,20 +565,15 @@ PyObject* SCA_PythonController::PySetScript(PyObject* value)
PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- //SCA_PythonController* self= static_cast<SCA_PythonController*>(static_cast<SCA_IController*>(static_cast<SCA_ILogicBrick*>(static_cast<CValue*>(static_cast<PyObjectPlus*>(self_v)))));
- // static_cast<void *>(dynamic_cast<Derived *>(obj)) - static_cast<void *>(obj)
-
SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
- return PyUnicode_FromString(self->m_scriptText);
+ return PyString_FromString(self->m_scriptText);
}
-
-
int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
- char *scriptArg = _PyUnicode_AsString(value);
+ char *scriptArg = PyString_AsString(value);
if (scriptArg==NULL) {
PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text");
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index 9311b3f355e..0c2af79c3a3 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -72,7 +72,7 @@ class SCA_PythonController : public SCA_IController
//virtual CValue* AddRef();
//virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
- SCA_PythonController(SCA_IObject* gameobj, int mode);
+ SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type);
virtual ~SCA_PythonController();
virtual CValue* GetReplica();
@@ -96,6 +96,10 @@ class SCA_PythonController : public SCA_IController
static PyObject* sPyAddActiveActuator(PyObject* self,
PyObject* args);
static SCA_IActuator* LinkedActuatorFromPy(PyObject *value);
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
KX_PYMETHOD_O(SCA_PythonController,Activate);
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index e903d10f9a5..a722590dd10 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -50,8 +50,9 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj,
SCA_RandomActuator::KX_RANDOMACT_MODE mode,
float para1,
float para2,
- const STR_String &propName)
- : SCA_IActuator(gameobj),
+ const STR_String &propName,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T),
m_propname(propName),
m_parameter1(para1),
m_parameter2(para2),
@@ -331,15 +332,19 @@ PyTypeObject SCA_RandomActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_RandomActuator::Parents[] = {
+ &SCA_RandomActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_RandomActuator::Methods[] = {
@@ -379,14 +384,14 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = {
PyObject* SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_RandomActuator* act = static_cast<SCA_RandomActuator*>(self);
- return PyLong_FromSsize_t(act->m_base->GetSeed());
+ return PyInt_FromLong(act->m_base->GetSeed());
}
int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
SCA_RandomActuator* act = static_cast<SCA_RandomActuator*>(self);
- if (PyLong_Check(value)) {
- int ival = PyLong_AsSsize_t(value);
+ if (PyInt_Check(value)) {
+ int ival = PyInt_AsLong(value);
act->m_base->SetSeed(ival);
return PY_SET_ATTR_SUCCESS;
} else {
@@ -395,6 +400,19 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_
}
}
+PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* SCA_RandomActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
/* 1. setSeed */
const char SCA_RandomActuator::SetSeed_doc[] =
"setSeed(seed)\n"
@@ -421,7 +439,7 @@ const char SCA_RandomActuator::GetSeed_doc[] =
PyObject* SCA_RandomActuator::PyGetSeed()
{
ShowDeprecationWarning("getSeed()", "the seed property");
- return PyLong_FromSsize_t(m_base->GetSeed());
+ return PyInt_FromLong(m_base->GetSeed());
}
/* 4. getPara1 */
@@ -455,7 +473,7 @@ const char SCA_RandomActuator::GetDistribution_doc[] =
PyObject* SCA_RandomActuator::PyGetDistribution()
{
ShowDeprecationWarning("getDistribution()", "the distribution property");
- return PyLong_FromSsize_t(m_distribution);
+ return PyInt_FromLong(m_distribution);
}
/* 9. setProperty */
@@ -490,7 +508,7 @@ const char SCA_RandomActuator::GetProperty_doc[] =
PyObject* SCA_RandomActuator::PyGetProperty()
{
ShowDeprecationWarning("getProperty()", "the 'propName' property");
- return PyUnicode_FromString(m_propname);
+ return PyString_FromString(m_propname);
}
/* 11. setBoolConst */
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h
index c7d3fe21217..59863589b60 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.h
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.h
@@ -85,7 +85,8 @@ class SCA_RandomActuator : public SCA_IActuator
KX_RANDOMACT_MODE mode,
float para1,
float para2,
- const STR_String &propName);
+ const STR_String &propName,
+ PyTypeObject* T=&Type);
virtual ~SCA_RandomActuator();
virtual bool Update();
@@ -96,6 +97,10 @@ class SCA_RandomActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
index e036a77707e..d5cbeef01ae 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -46,8 +46,9 @@
SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
- int startseed)
- : SCA_ISensor(gameobj,eventmgr)
+ int startseed,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T)
{
m_basegenerator = new SCA_RandomNumberGenerator(startseed);
Init();
@@ -146,15 +147,19 @@ PyTypeObject SCA_RandomSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_RandomSensor::Parents[] = {
+ &SCA_RandomSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_RandomSensor::Methods[] = {
@@ -172,6 +177,19 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = {
{NULL} //Sentinel
};
+PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_RandomSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ISensor);
+}
+
/* 1. setSeed */
const char SCA_RandomSensor::SetSeed_doc[] =
"setSeed(seed)\n"
@@ -198,7 +216,7 @@ const char SCA_RandomSensor::GetSeed_doc[] =
"\tequal series.\n";
PyObject* SCA_RandomSensor::PyGetSeed() {
ShowDeprecationWarning("getSeed()", "the seed property");
- return PyLong_FromSsize_t(m_basegenerator->GetSeed());
+ return PyInt_FromLong(m_basegenerator->GetSeed());
}
/* 3. getLastDraw */
@@ -207,24 +225,24 @@ const char SCA_RandomSensor::GetLastDraw_doc[] =
"\tReturn the last value that was drawn.\n";
PyObject* SCA_RandomSensor::PyGetLastDraw() {
ShowDeprecationWarning("getLastDraw()", "the lastDraw property");
- return PyLong_FromSsize_t(m_lastdraw);
+ return PyInt_FromLong(m_lastdraw);
}
PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v);
- return PyLong_FromSsize_t(self->m_basegenerator->GetSeed());
+ return PyInt_FromLong(self->m_basegenerator->GetSeed());
}
int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v);
- if (!PyLong_Check(value)) {
+ if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer");
return PY_SET_ATTR_FAIL;
}
- self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value));
+ self->m_basegenerator->SetSeed(PyInt_AsLong(value));
return PY_SET_ATTR_SUCCESS;
}
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h
index 5e66c36cccf..b2bf2440966 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.h
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.h
@@ -48,7 +48,8 @@ class SCA_RandomSensor : public SCA_ISensor
public:
SCA_RandomSensor(class SCA_EventManager* rndmgr,
SCA_IObject* gameobj,
- int startseed);
+ int startseed,
+ PyTypeObject* T=&Type);
virtual ~SCA_RandomSensor();
virtual CValue* GetReplica();
virtual void ProcessReplica();
@@ -60,6 +61,10 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* 1. setSeed */
KX_PYMETHOD_DOC_VARARGS(SCA_RandomSensor,SetSeed);
/* 2. getSeed */
diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp
index 527adc70cc6..aee8e26c21a 100644
--- a/source/gameengine/GameLogic/SCA_XNORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XNORController.cpp
@@ -42,9 +42,10 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj)
+SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_IController(gameobj)
+ SCA_IController(gameobj,T)
{
}
@@ -119,15 +120,19 @@ PyTypeObject SCA_XNORController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_XNORController::Parents[] = {
+ &SCA_XNORController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_XNORController::Methods[] = {
@@ -138,4 +143,12 @@ PyAttributeDef SCA_XNORController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_XNORController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_XNORController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h
index 18e77fae665..4aad5763cb0 100644
--- a/source/gameengine/GameLogic/SCA_XNORController.h
+++ b/source/gameengine/GameLogic/SCA_XNORController.h
@@ -39,7 +39,7 @@ class SCA_XNORController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_XNORController(SCA_IObject* gameobj);
+ SCA_XNORController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
virtual ~SCA_XNORController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
@@ -48,6 +48,9 @@ public:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_XNORCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp
index c0916224fe6..5afb3a750f5 100644
--- a/source/gameengine/GameLogic/SCA_XORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XORController.cpp
@@ -42,9 +42,10 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-SCA_XORController::SCA_XORController(SCA_IObject* gameobj)
+SCA_XORController::SCA_XORController(SCA_IObject* gameobj,
+ PyTypeObject* T)
:
- SCA_IController(gameobj)
+ SCA_IController(gameobj,T)
{
}
@@ -119,15 +120,19 @@ PyTypeObject SCA_XORController::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject SCA_XORController::Parents[] = {
+ &SCA_XORController::Type,
&SCA_IController::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef SCA_XORController::Methods[] = {
@@ -138,4 +143,12 @@ PyAttributeDef SCA_XORController::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* SCA_XORController::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IController);
+}
+
+PyObject* SCA_XORController::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IController);
+}
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h
index 2607a533661..feb9f2ed07c 100644
--- a/source/gameengine/GameLogic/SCA_XORController.h
+++ b/source/gameengine/GameLogic/SCA_XORController.h
@@ -39,10 +39,18 @@ class SCA_XORController : public SCA_IController
Py_Header;
//virtual void Trigger(class SCA_LogicManager* logicmgr);
public:
- SCA_XORController(SCA_IObject* gameobj);
+ SCA_XORController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
virtual ~SCA_XORController();
virtual CValue* GetReplica();
virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+
};
#endif //__KX_XORCONTROLLER
diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile
index 4a952856739..84b4a4170a9 100644
--- a/source/gameengine/GamePlayer/common/Makefile
+++ b/source/gameengine/GamePlayer/common/Makefile
@@ -50,6 +50,8 @@ CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I$(NAN_FUZZICS)/include
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_SUMO)/include
+CPPFLAGS += -I$(NAN_SOLID)/include
CPPFLAGS += -I$(NAN_PNG)/include
CPPFLAGS += -I$(NAN_ZLIB)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
@@ -67,6 +69,7 @@ CPPFLAGS += -I../../../gameengine/Network/LoopBackNetwork
CPPFLAGS += -I../../../gameengine/Rasterizer
CPPFLAGS += -I../../../gameengine/SceneGraph
CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../../../gameengine/Physics/Sumo
CPPFLAGS += -I../../../gameengine/Physics/common
###############################
diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript
index f899385c841..e96b2c5400b 100644
--- a/source/gameengine/GamePlayer/common/SConscript
+++ b/source/gameengine/GamePlayer/common/SConscript
@@ -59,6 +59,11 @@ incs = ['.',
# 'unix/GPU_System.cpp']
# gp_common_env.Append ( CPPPATH = ['unix'])
+if env['WITH_BF_SOLID']:
+ incs.append('#source/gameengine/Physics/Sumo')
+ incs.append('#source/gameengine/Physics/Sumo/Fuzzics/include')
+ incs += Split(env['BF_SOLID_INC'])
+
incs += Split(env['BF_PYTHON_INC'])
incs += Split(env['BF_PNG_INC'])
incs += Split(env['BF_ZLIB_INC'])
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp
index 0ef087efbfe..a5dec02c753 100644
--- a/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp
+++ b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp
@@ -44,6 +44,9 @@
#include "NG_LoopBackNetworkDeviceInterface.h"
#include "SND_DeviceManager.h"
#include "KX_BlenderSceneConverter.h"
+#ifdef USE_SUMO_SOLID
+ #include "SM_Scene.h"
+#endif
#include "KX_KetsjiEngine.h"
#include "GPC_RenderTools.h"
diff --git a/source/gameengine/GamePlayer/common/unix/Makefile b/source/gameengine/GamePlayer/common/unix/Makefile
index 08c52ddc904..90342c7b735 100644
--- a/source/gameengine/GamePlayer/common/unix/Makefile
+++ b/source/gameengine/GamePlayer/common/unix/Makefile
@@ -57,8 +57,10 @@ CPPFLAGS += -I../../../../gameengine/Rasterizer/RAS_OpenGLRasterizer
CPPFLAGS += -I../../../../gameengine/SceneGraph
CPPFLAGS += -I$(NAN_FUZZICS)/include
+CPPFLAGS += -I$(NAN_SUMO)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_SOLID)/include
# Blender stuff
CPPFLAGS += -I../../../../blender/blenkernel
diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript
index 19234cb663c..390b6f5e089 100644
--- a/source/gameengine/GamePlayer/ghost/SConscript
+++ b/source/gameengine/GamePlayer/ghost/SConscript
@@ -41,6 +41,10 @@ incs = ['.',
'#source/blender/gpu',
'#extern/glew/include']
+if env['WITH_BF_SOLID']:
+ incs.append(['#source/gameengine/Physics/Sumo', '#source/gameengine/Physics/Sumo/Fuzzics/include'])
+ incs += Split(env['BF_SOLID_INC'])
+
incs += Split(env['BF_PYTHON_INC'])
cxxflags = []
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 8bde5dd3a51..c5c517c8a65 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -113,8 +113,8 @@ bool BL_Shader::Ok()const
return (mShader !=0 && mOk && mUse);
}
-BL_Shader::BL_Shader()
-: PyObjectPlus(),
+BL_Shader::BL_Shader(PyTypeObject *T)
+: PyObjectPlus(T),
mShader(0),
mPass(1),
mOk(0),
@@ -728,6 +728,17 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len)
}
}
+
+PyObject* BL_Shader::py_getattro(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* BL_Shader::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+
PyMethodDef BL_Shader::Methods[] =
{
// creation
@@ -781,17 +792,21 @@ PyTypeObject BL_Shader::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+
+PyParentObject BL_Shader::Parents[] = {
+ &BL_Shader::Type,
+ &PyObjectPlus::Type,
+ NULL
+};
+
+
KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
{
if(mShader !=0 && mOk )
@@ -833,17 +848,17 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
{
- return PyLong_FromSsize_t( ( mShader !=0 && mOk ) );
+ return PyInt_FromLong( ( mShader !=0 && mOk ) );
}
KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
{
- return PyUnicode_FromString(vertProg?vertProg:"");
+ return PyString_FromString(vertProg?vertProg:"");
}
KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
{
- return PyUnicode_FromString(fragProg?fragProg:"");
+ return PyString_FromString(fragProg?fragProg:"");
}
KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
@@ -1208,7 +1223,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2
for(unsigned int i=0; (i<list_size && i<4); i++)
{
PyObject *item = PySequence_GetItem(listPtr, i);
- array_data[i] = PyLong_AsSsize_t(item);
+ array_data[i] = PyInt_AsLong(item);
Py_DECREF(item);
}
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 42969996b3e..7db40e778ae 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -120,7 +120,7 @@ private:
void ClearUniforms();
public:
- BL_Shader();
+ BL_Shader(PyTypeObject *T=&Type);
virtual ~BL_Shader();
// Unused for now tangent is set as
@@ -202,7 +202,9 @@ public:
void SetUniform(int uniform, const int val);
// Python interface
- virtual PyObject* py_repr(void) { return PyUnicode_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); }
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual PyObject* py_repr(void) { return PyString_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); }
// -----------------------------------
KX_PYMETHOD_DOC( BL_Shader, setSource );
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
index 7cb287d02b2..63773352d96 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
@@ -41,8 +41,9 @@ KX_NetworkMessageActuator::KX_NetworkMessageActuator(
const STR_String &toPropName,
const STR_String &subject,
int bodyType,
- const STR_String &body) :
- SCA_IActuator(gameobj),
+ const STR_String &body,
+ PyTypeObject* T) :
+ SCA_IActuator(gameobj,T),
m_networkscene(networkscene),
m_toPropName(toPropName),
m_subject(subject),
@@ -117,15 +118,19 @@ PyTypeObject KX_NetworkMessageActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_NetworkMessageActuator::Parents[] = {
+ &KX_NetworkMessageActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_NetworkMessageActuator::Methods[] = {
@@ -150,6 +155,18 @@ PyAttributeDef KX_NetworkMessageActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_NetworkMessageActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_NetworkMessageActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_NetworkMessageActuator::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_IActuator);
+}
+
// Deprecated ----->
// 1. SetToPropName
PyObject* KX_NetworkMessageActuator::PySetToPropName(
@@ -223,4 +240,4 @@ PyObject* KX_NetworkMessageActuator::PySetBody(
Py_RETURN_NONE;
}
-// <----- Deprecated
+// <----- Deprecated \ No newline at end of file
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
index b4f55f2a466..cf92fd46fe0 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
@@ -50,7 +50,8 @@ public:
const STR_String &toPropName,
const STR_String &subject,
int bodyType,
- const STR_String &body);
+ const STR_String &body,
+ PyTypeObject* T=&Type);
virtual ~KX_NetworkMessageActuator();
virtual bool Update();
@@ -60,6 +61,10 @@ public:
/* Python interface ------------------------------------------- */
/* ------------------------------------------------------------ */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// Deprecated ----->
KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName);
KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject);
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index 78dda1f6db7..8ddcd87b66f 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -50,9 +50,10 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor(
class KX_NetworkEventManager* eventmgr, // our eventmanager
class NG_NetworkScene *NetworkScene, // our scene
SCA_IObject* gameobj, // the sensor controlling object
- const STR_String &subject
+ const STR_String &subject,
+ PyTypeObject* T
) :
- SCA_ISensor(gameobj,eventmgr),
+ SCA_ISensor(gameobj,eventmgr,T),
m_Networkeventmgr(eventmgr),
m_NetworkScene(NetworkScene),
m_subject(subject),
@@ -181,15 +182,19 @@ PyTypeObject KX_NetworkMessageSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_NetworkMessageSensor::Parents[] = {
+ &KX_NetworkMessageSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_NetworkMessageSensor::Methods[] = {
@@ -221,6 +226,18 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* KX_NetworkMessageSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) {
+ return SCA_ISensor::py_setattro(attr, value);
+}
+
PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
@@ -250,7 +267,7 @@ const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] =
PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value)
{
ShowDeprecationWarning("setSubjectFilterText()", "subject");
- char* Subject = _PyUnicode_AsString(value);
+ char* Subject = PyString_AsString(value);
if (Subject==NULL) {
PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message");
return NULL;
@@ -268,7 +285,7 @@ const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount()
{
ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount");
- return PyLong_FromSsize_t(long(m_frame_message_count));
+ return PyInt_FromLong(long(m_frame_message_count));
}
// 3. Get the message bodies
@@ -294,7 +311,7 @@ const char KX_NetworkMessageSensor::GetSubject_doc[] =
PyObject* KX_NetworkMessageSensor::PyGetSubject()
{
ShowDeprecationWarning("getSubject()", "subject");
- return PyUnicode_FromString(m_subject ? m_subject : "");
+ return PyString_FromString(m_subject ? m_subject : "");
}
// 5. Get the message subjects
@@ -311,4 +328,4 @@ PyObject* KX_NetworkMessageSensor::PyGetSubjects()
return (new CListValue())->NewProxy(true);
}
}
-// <----- Deprecated
+// <----- Deprecated \ No newline at end of file
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
index ade87697303..53183f33826 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -57,7 +57,8 @@ public:
KX_NetworkEventManager* eventmgr, // our eventmanager
NG_NetworkScene *NetworkScene, // our scene
SCA_IObject* gameobj, // the sensor controlling object
- const STR_String &subject
+ const STR_String &subject,
+ PyTypeObject* T=&Type
);
virtual ~KX_NetworkMessageSensor();
@@ -71,6 +72,10 @@ public:
/* Python interface -------------------------------------------- */
/* ------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// Deprecated ----->
KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText);
KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 314becc702d..30057fc039d 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -42,8 +42,10 @@ BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
//static PyObject *gTextureDict = 0;
-KX_BlenderMaterial::KX_BlenderMaterial()
-: PyObjectPlus(),
+KX_BlenderMaterial::KX_BlenderMaterial(
+ PyTypeObject *T
+ )
+: PyObjectPlus(T),
RAS_IPolyMaterial(),
mMaterial(NULL),
mShader(0),
@@ -811,17 +813,36 @@ PyTypeObject KX_BlenderMaterial::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+
+PyParentObject KX_BlenderMaterial::Parents[] = {
+ &KX_BlenderMaterial::Type,
+ &PyObjectPlus::Type,
+ NULL
+};
+
+
+PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* KX_BlenderMaterial::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue)
+{
+ return PyObjectPlus::py_setattro(attr, pyvalue);
+}
+
+
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
{
if( !GLEW_ARB_fragment_shader) {
@@ -891,7 +912,7 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
{
- return PyLong_FromSsize_t( GetMaterialIndex() );
+ return PyInt_FromLong( GetMaterialIndex() );
}
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 1f5edc1d7d1..b29f2df98db 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -23,7 +23,9 @@ class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial
Py_Header;
public:
// --------------------------------
- KX_BlenderMaterial();
+ KX_BlenderMaterial(
+ PyTypeObject* T=&Type
+ );
void Initialize(
class KX_Scene* scene,
BL_Material* mat,
@@ -81,7 +83,10 @@ public:
);
// --------------------------------
- virtual PyObject* py_repr(void) { return PyUnicode_FromString(mMaterial->matname.ReadPtr()); }
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
+ virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); }
KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader );
KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex );
diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp
index bfca81f45d9..8511526fd5f 100644
--- a/source/gameengine/Ketsji/KX_CDActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CDActuator.cpp
@@ -48,8 +48,9 @@ KX_CDActuator::KX_CDActuator(SCA_IObject* gameobject,
KX_CDACT_TYPE type,
int track,
short start,
- short end)
- : SCA_IActuator(gameobject)
+ short end,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobject,T)
{
m_soundscene = soundscene;
m_type = type;
@@ -170,17 +171,25 @@ PyTypeObject KX_CDActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject KX_CDActuator::Parents[] = {
+ &KX_CDActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_CDActuator::Methods[] = {
// Deprecated ----->
{"setGain",(PyCFunction) KX_CDActuator::sPySetGain,METH_VARARGS,NULL},
@@ -208,6 +217,22 @@ int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *a
return PY_SET_ATTR_SUCCESS;
}
+PyObject* KX_CDActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_CDActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
+
+
KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, startCD,
"startCD()\n"
"\tStarts the CD playing.\n")
@@ -248,8 +273,8 @@ KX_PYMETHODDEF_DOC_O(KX_CDActuator, playTrack,
"playTrack(trackNumber)\n"
"\tPlays the track selected.\n")
{
- if (PyLong_Check(value)) {
- int track = PyLong_AsSsize_t(value);
+ if (PyInt_Check(value)) {
+ int track = PyInt_AsLong(value);
SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK);
SND_CDObject::Instance()->SetTrack(track);
SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY);
diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h
index b01ad73777e..2fd05ab72e5 100644
--- a/source/gameengine/Ketsji/KX_CDActuator.h
+++ b/source/gameengine/Ketsji/KX_CDActuator.h
@@ -68,7 +68,8 @@ public:
KX_CDACT_TYPE type,
int track,
short start,
- short end);
+ short end,
+ PyTypeObject* T=&Type);
~KX_CDActuator();
@@ -80,6 +81,10 @@ public:
/* Python interface --------------------------------------------------- */
/* -------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// Deprecated ----->
KX_PYMETHOD_VARARGS(KX_CDActuator,SetGain);
KX_PYMETHOD_VARARGS(KX_CDActuator,GetGain);
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index f762699f780..40f6c99c03c 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -42,9 +42,10 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
SG_Callbacks callbacks,
const RAS_CameraData& camdata,
bool frustum_culling,
- bool delete_node)
+ bool delete_node,
+ PyTypeObject *T)
:
- KX_GameObject(sgReplicationInfo,callbacks),
+ KX_GameObject(sgReplicationInfo,callbacks,T),
m_camdata(camdata),
m_dirty(true),
m_normalized(false),
@@ -550,19 +551,41 @@ PyTypeObject KX_Camera::Type = {
&KX_GameObject::Sequence,
&KX_GameObject::Mapping,
0,0,0,
- NULL,
- NULL,
+ py_base_getattro,
+ py_base_setattro,
0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ Py_TPFLAGS_DEFAULT,
0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &KX_GameObject::Type,
- 0,0,0,0,0,0,
- py_base_new
+ Methods
+};
+
+
+
+
+
+
+PyParentObject KX_Camera::Parents[] = {
+ &KX_Camera::Type,
+ &KX_GameObject::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
};
+PyObject* KX_Camera::py_getattro(PyObject *attr)
+{
+ py_getattro_up(KX_GameObject);
+}
+
+PyObject* KX_Camera::py_getattro_dict() {
+ py_getattro_dict_up(KX_GameObject);
+}
+
+int KX_Camera::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(KX_GameObject);
+}
+
KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
"sphereInsideFrustum(center, radius) -> Integer\n"
"\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n"
@@ -588,7 +611,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
MT_Point3 center;
if (PyVecTo(pycenter, center))
{
- return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */
+ return PyInt_FromLong(SphereInsideFrustum(center, radius)); /* new ref */
}
}
@@ -639,7 +662,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum,
return NULL;
}
- return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */
+ return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */
}
KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum,
@@ -661,7 +684,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum,
MT_Point3 point;
if (PyVecTo(value, point))
{
- return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */
+ return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */
}
PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument.");
@@ -929,11 +952,11 @@ PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBU
PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
-{ return PyLong_FromSsize_t(INSIDE); }
+{ return PyInt_FromLong(INSIDE); }
PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
-{ return PyLong_FromSsize_t(OUTSIDE); }
+{ return PyInt_FromLong(OUTSIDE); }
PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
-{ return PyLong_FromSsize_t(INTERSECT); }
+{ return PyInt_FromLong(INTERSECT); }
bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix)
@@ -955,14 +978,14 @@ bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok
}
}
- if (PyUnicode_Check(value)) {
- STR_String value_str = _PyUnicode_AsString(value);
+ if (PyString_Check(value)) {
+ STR_String value_str = PyString_AsString(value);
*object = KX_GetActiveScene()->FindCamera(value_str);
if (*object) {
return true;
} else {
- PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, _PyUnicode_AsString(value));
+ PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, PyString_AsString(value));
return false;
}
}
@@ -1119,7 +1142,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay,
PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect));
PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist));
if (propName)
- PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName));
+ PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName));
PyObject* ret= this->PyrayCastTo(argValue,NULL);
Py_DECREF(argValue);
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
index 74c8e6d4e4f..aef21cd91e4 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -143,7 +143,7 @@ public:
enum { INSIDE, INTERSECT, OUTSIDE } ;
- KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false);
+ KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false, PyTypeObject *T = &Type);
virtual ~KX_Camera();
/**
@@ -265,7 +265,6 @@ public:
*/
int GetViewportTop() const;
- virtual int GetGameObjectType() { return OBJ_CAMERA; }
KX_PYMETHOD_DOC_VARARGS(KX_Camera, sphereInsideFrustum);
KX_PYMETHOD_DOC_O(KX_Camera, boxInsideFrustum);
@@ -283,6 +282,10 @@ public:
KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition);
KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect);
KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenRay);
+
+ virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
static PyObject* pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index 3d3b68ed85d..f8557dac2c4 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -56,9 +56,10 @@ KX_CameraActuator::KX_CameraActuator(
float hght,
float minhght,
float maxhght,
- bool xytog
+ bool xytog,
+ PyTypeObject* T
):
- SCA_IActuator(gameobj),
+ SCA_IActuator(gameobj, T),
m_ob (obj),
m_height (hght),
m_minHeight (minhght),
@@ -384,15 +385,19 @@ PyTypeObject KX_CameraActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_CameraActuator::Parents[] = {
+ &KX_CameraActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_CameraActuator::Methods[] = {
@@ -419,6 +424,18 @@ PyAttributeDef KX_CameraActuator::Attributes[] = {
{NULL}
};
+PyObject* KX_CameraActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_CameraActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) {
+ py_setattro_up(SCA_IActuator);
+}
+
/* get obj ---------------------------------------------------------- */
const char KX_CameraActuator::GetObject_doc[] =
"getObject(name_only = 1)\n"
@@ -437,7 +454,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* args)
Py_RETURN_NONE;
if (ret_name_only)
- return PyUnicode_FromString(m_ob->GetName().ReadPtr());
+ return PyString_FromString(m_ob->GetName().ReadPtr());
else
return m_ob->GetProxy();
}
@@ -562,7 +579,7 @@ const char KX_CameraActuator::GetXY_doc[] =
PyObject* KX_CameraActuator::PyGetXY()
{
ShowDeprecationWarning("getXY()", "the xy property");
- return PyLong_FromSsize_t(m_x);
+ return PyInt_FromLong(m_x);
}
PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h
index 057c6fed770..efa4e2f38d7 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.h
+++ b/source/gameengine/Ketsji/KX_CameraActuator.h
@@ -91,7 +91,9 @@ private :
float hght,
float minhght,
float maxhght,
- bool xytog
+ bool xytog,
+ PyTypeObject* T=&Type
+
);
@@ -118,6 +120,10 @@ private :
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
/* set object to look at */
KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject);
/* get current object */
diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
index 1898dc71ef8..077ac96f0ac 100644
--- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h
+++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
@@ -30,6 +30,9 @@
#define __KX_CLIENTOBJECT_INFO_H
/* Note, the way this works with/without sumo is a bit odd */
+#ifdef USE_SUMO_SOLID
+#include <SM_Object.h>
+#endif //USE_SUMO_SOLID
#include <list>
@@ -39,6 +42,9 @@ class KX_GameObject;
* Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
*/
struct KX_ClientObjectInfo
+#ifdef USE_SUMO_SOLID
+ : public SM_ClientObject
+#endif
{
enum clienttype {
STATIC,
@@ -53,12 +59,18 @@ struct KX_ClientObjectInfo
std::list<SCA_ISensor*> m_sensors;
public:
KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) :
+#ifdef USE_SUMO_SOLID
+ SM_ClientObject(),
+#endif
m_type(type),
m_gameobject(gameobject),
m_auxilary_info(auxilary_info)
{}
KX_ClientObjectInfo(const KX_ClientObjectInfo &copy) :
+#ifdef USE_SUMO_SOLID
+ SM_ClientObject(copy),
+#endif
m_type(copy.m_type),
m_gameobject(copy.m_gameobject),
m_auxilary_info(copy.m_auxilary_info)
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index d09eae647c8..bd03dea486b 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -54,8 +54,9 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj,
int locrotxyz,
int time,
int option,
- char *property) :
- SCA_IActuator(gameobj),
+ char *property,
+ PyTypeObject* T) :
+ SCA_IActuator(gameobj, T),
m_refDirVector(refDir),
m_currentTime(0)
{
@@ -580,15 +581,19 @@ PyTypeObject KX_ConstraintActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_ConstraintActuator::Parents[] = {
+ &KX_ConstraintActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_ConstraintActuator::Methods[] = {
@@ -634,6 +639,21 @@ PyAttributeDef KX_ConstraintActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_ConstraintActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
+
int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ConstraintActuator* act = static_cast<KX_ConstraintActuator*>(self);
@@ -671,7 +691,7 @@ const char KX_ConstraintActuator::GetDamp_doc[] =
"\tReturns the damping parameter.\n";
PyObject* KX_ConstraintActuator::PyGetDamp(){
ShowDeprecationWarning("getDamp()", "the damp property");
- return PyLong_FromSsize_t(m_posDampTime);
+ return PyInt_FromLong(m_posDampTime);
}
/* 2. setRotDamp */
@@ -698,7 +718,7 @@ const char KX_ConstraintActuator::GetRotDamp_doc[] =
"\tReturns the damping time for application of the constraint.\n";
PyObject* KX_ConstraintActuator::PyGetRotDamp(){
ShowDeprecationWarning("getRotDamp()", "the rotDamp property");
- return PyLong_FromSsize_t(m_rotDampTime);
+ return PyInt_FromLong(m_rotDampTime);
}
/* 2. setDirection */
@@ -771,7 +791,7 @@ const char KX_ConstraintActuator::GetOption_doc[] =
"\tReturns the option parameter.\n";
PyObject* KX_ConstraintActuator::PyGetOption(){
ShowDeprecationWarning("getOption()", "the option property");
- return PyLong_FromSsize_t(m_option);
+ return PyInt_FromLong(m_option);
}
/* 2. setTime */
@@ -800,7 +820,7 @@ const char KX_ConstraintActuator::GetTime_doc[] =
"\tReturns the time parameter.\n";
PyObject* KX_ConstraintActuator::PyGetTime(){
ShowDeprecationWarning("getTime()", "the time property");
- return PyLong_FromSsize_t(m_activeTime);
+ return PyInt_FromLong(m_activeTime);
}
/* 2. setProperty */
@@ -829,7 +849,7 @@ const char KX_ConstraintActuator::GetProperty_doc[] =
"\tReturns the property parameter.\n";
PyObject* KX_ConstraintActuator::PyGetProperty(){
ShowDeprecationWarning("getProperty()", "the 'property' property");
- return PyUnicode_FromString(m_property.Ptr());
+ return PyString_FromString(m_property.Ptr());
}
/* 4. setDistance */
@@ -958,7 +978,7 @@ const char KX_ConstraintActuator::GetLimit_doc[] =
"\tReturns the type of constraint.\n";
PyObject* KX_ConstraintActuator::PyGetLimit() {
ShowDeprecationWarning("setLimit()", "the limit property");
- return PyLong_FromSsize_t(m_locrot);
+ return PyInt_FromLong(m_locrot);
}
/* eof */
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index 677904aedc9..40607b44947 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -126,7 +126,8 @@ protected:
int locrot,
int time,
int option,
- char *property);
+ char *property,
+ PyTypeObject* T=&Type);
virtual ~KX_ConstraintActuator();
virtual CValue* GetReplica() {
KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this);
@@ -140,6 +141,10 @@ protected:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_check_min(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index ec7bb470235..c5cf67af67d 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -38,8 +38,8 @@
KX_ConstraintWrapper::KX_ConstraintWrapper(
PHY_ConstraintType ctype,
int constraintId,
- PHY_IPhysicsEnvironment* physenv) :
- PyObjectPlus(),
+ PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) :
+ PyObjectPlus(T),
m_constraintId(constraintId),
m_constraintType(ctype),
m_physenv(physenv)
@@ -51,7 +51,7 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper()
PyObject* KX_ConstraintWrapper::PyGetConstraintId()
{
- return PyLong_FromSsize_t(m_constraintId);
+ return PyInt_FromLong(m_constraintId);
}
@@ -99,17 +99,37 @@ PyTypeObject KX_ConstraintWrapper::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
+};
+
+PyParentObject KX_ConstraintWrapper::Parents[] = {
+ &KX_ConstraintWrapper::Type,
+ NULL
+};
+
+//here you can search for existing data members (like mass,friction etc.)
+PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* KX_ConstraintWrapper::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* value)
+{
+ py_setattro_up(PyObjectPlus);
};
+
+
+
+
PyMethodDef KX_ConstraintWrapper::Methods[] = {
{"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_NOARGS},
{"setParam",(PyCFunction) KX_ConstraintWrapper::sPySetParam, METH_VARARGS},
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index 74670944415..03813e0f167 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -35,8 +35,11 @@
class KX_ConstraintWrapper : public PyObjectPlus
{
Py_Header;
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
public:
- KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv);
+ KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
virtual ~KX_ConstraintWrapper ();
int getConstraintId() { return m_constraintId;};
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index 9d3b9cdaf74..74042366bae 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -32,8 +32,11 @@
/* These are defined by the build system... */
//but the build system is broken, because it doesn't allow for 2 or more defines at once.
//Please leave Sumo _AND_ Bullet enabled
+//#define USE_SUMO_SOLID // scons defines this
#define USE_BULLET
+//#define USE_ODE
+
//on visual studio 7/8, always enable BULLET for now
//you can have multiple physics engines running anyway, and
//the scons build system doesn't really support this at the moment.
@@ -145,6 +148,20 @@ struct KX_ObjectProperties
} m_boundobject;
};
+#ifdef USE_ODE
+
+
+void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop);
+
+
+#endif //USE_ODE
+
+
void KX_ConvertDynamoObject(KX_GameObject* gameobj,
RAS_MeshObject* meshobj,
KX_Scene* kxscene,
@@ -152,6 +169,19 @@ void KX_ConvertDynamoObject(KX_GameObject* gameobj,
struct PHY_MaterialProps* smmaterial,
struct KX_ObjectProperties* objprop);
+#ifdef USE_SUMO_SOLID
+
+void KX_ConvertSumoObject( class KX_GameObject* gameobj,
+ class RAS_MeshObject* meshobj,
+ class KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop);
+
+void KX_ClearSumoSharedShapes();
+bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj);
+
+#endif
#ifdef USE_BULLET
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index 64b5760de28..51c41c0686d 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -32,6 +32,7 @@
#include "MT_assert.h"
+// defines USE_ODE to choose physics engine
#include "KX_ConvertPhysicsObject.h"
#include "BL_DeformableGameObject.h"
#include "RAS_MeshObject.h"
@@ -55,6 +56,597 @@ extern "C"{
#include "BKE_DerivedMesh.h"
}
+#ifdef USE_ODE
+
+#include "KX_OdePhysicsController.h"
+#include "OdePhysicsEnvironment.h"
+#endif //USE_ODE
+
+
+// USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
+#ifdef USE_SUMO_SOLID
+
+
+#include "SumoPhysicsEnvironment.h"
+#include "KX_SumoPhysicsController.h"
+
+
+// sumo physics specific
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+#include "SM_Scene.h"
+#include "SM_ClientObjectInfo.h"
+
+#include "KX_SumoPhysicsController.h"
+
+struct KX_PhysicsInstance
+{
+ DT_VertexBaseHandle m_vertexbase;
+ RAS_DisplayArray* m_darray;
+ RAS_IPolyMaterial* m_material;
+
+ KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat)
+ : m_vertexbase(vertex_base),
+ m_darray(darray),
+ m_material(mat)
+ {
+ }
+
+ ~KX_PhysicsInstance()
+ {
+ DT_DeleteVertexBase(m_vertexbase);
+ }
+};
+
+static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
+static GEN_Map<GEN_HashedPtr, KX_PhysicsInstance*> map_gamemesh_to_instance;
+
+// forward declarations
+static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
+static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
+
+void KX_ConvertSumoObject( KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ PHY_ShapeProps* kxshapeprops,
+ PHY_MaterialProps* kxmaterial,
+ struct KX_ObjectProperties* objprop)
+
+
+{
+ SM_ShapeProps* smprop = new SM_ShapeProps;
+
+ smprop->m_ang_drag = kxshapeprops->m_ang_drag;
+ smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
+ smprop->m_do_fh = kxshapeprops->m_do_fh;
+ smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
+ smprop->m_friction_scaling[0] = kxshapeprops->m_friction_scaling[0];
+ smprop->m_friction_scaling[1] = kxshapeprops->m_friction_scaling[1];
+ smprop->m_friction_scaling[2] = kxshapeprops->m_friction_scaling[2];
+ smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia;
+ smprop->m_lin_drag = kxshapeprops->m_lin_drag;
+ smprop->m_mass = kxshapeprops->m_mass;
+ smprop->m_radius = objprop->m_radius;
+
+
+ SM_MaterialProps* smmaterial = new SM_MaterialProps;
+
+ smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
+ smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
+ smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
+ smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
+ smmaterial->m_friction = kxmaterial->m_friction;
+ smmaterial->m_restitution = kxmaterial->m_restitution;
+
+ SumoPhysicsEnvironment* sumoEnv =
+ (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+
+ SM_Scene* sceneptr = sumoEnv->GetSumoScene();
+
+ SM_Object* sumoObj=NULL;
+
+ if (objprop->m_dyna && objprop->m_isactor)
+ {
+ DT_ShapeHandle shape = NULL;
+ bool polytope = false;
+ switch (objprop->m_boundclass)
+ {
+ case KX_BOUNDBOX:
+ shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0],
+ objprop->m_boundobject.box.m_extends[1],
+ objprop->m_boundobject.box.m_extends[2]);
+ smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
+ objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
+ objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
+ smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
+ break;
+ case KX_BOUNDCYLINDER:
+ shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
+ smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
+ break;
+ case KX_BOUNDCONE:
+ shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
+ smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
+ break;
+ /* Dynamic mesh objects. WARNING! slow. */
+ case KX_BOUNDPOLYTOPE:
+ polytope = true;
+ // fall through
+ case KX_BOUNDMESH:
+ if (meshobj && meshobj->NumPolygons() > 0)
+ {
+ if ((shape = CreateShapeFromMesh(meshobj, polytope)))
+ {
+ // TODO: calculate proper inertia
+ smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
+ break;
+ }
+ }
+ /* If CreateShapeFromMesh fails, fall through and use sphere */
+ default:
+ case KX_BOUNDSPHERE:
+ shape = DT_NewSphere(objprop->m_radius);
+ smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
+ break;
+
+ }
+
+ sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
+
+ sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
+
+ BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
+
+ }
+ else {
+ // non physics object
+ if (meshobj)
+ {
+ int numpolys = meshobj->NumPolygons();
+ {
+
+ DT_ShapeHandle complexshape=0;
+ bool polytope = false;
+
+ switch (objprop->m_boundclass)
+ {
+ case KX_BOUNDBOX:
+ complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]);
+ break;
+ case KX_BOUNDSPHERE:
+ complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
+ break;
+ case KX_BOUNDCYLINDER:
+ complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
+ break;
+ case KX_BOUNDCONE:
+ complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
+ break;
+ case KX_BOUNDPOLYTOPE:
+ polytope = true;
+ // fall through
+ default:
+ case KX_BOUNDMESH:
+ if (numpolys>0)
+ {
+ complexshape = CreateShapeFromMesh(meshobj, polytope);
+ //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
+/* if (!complexshape)
+ {
+ // Something has to be done here - if the object has no polygons, it will not be able to have
+ // sensors attached to it.
+ DT_Vector3 pt = {0., 0., 0.};
+ complexshape = DT_NewSphere(1.0);
+ objprop->m_ghost = evilObject = true;
+ } */
+ }
+ break;
+ }
+
+ if (complexshape)
+ {
+ SM_Object *dynamicParent = NULL;
+
+ if (objprop->m_dynamic_parent)
+ {
+ // problem is how to find the dynamic parent
+ // in the scenegraph
+ KX_SumoPhysicsController* sumoctrl =
+ (KX_SumoPhysicsController*)
+ objprop->m_dynamic_parent->GetPhysicsController();
+
+ if (sumoctrl)
+ {
+ dynamicParent = sumoctrl->GetSumoObject();
+ }
+
+ MT_assert(dynamicParent);
+ }
+
+
+ sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);
+ const STR_String& matname=meshobj->GetMaterialName(0);
+
+
+ BL_RegisterSumoObject(gameobj,sceneptr,
+ sumoObj,
+ matname,
+ objprop->m_dyna,
+ objprop->m_isactor);
+ }
+ }
+ }
+ }
+
+ // physics object get updated here !
+
+
+ // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
+
+ if (objprop->m_in_active_layer && sumoObj)
+ {
+ sceneptr->add(*sumoObj);
+ }
+
+}
+
+
+
+static void BL_RegisterSumoObject(
+ KX_GameObject* gameobj,
+ class SM_Scene* sumoScene,
+ class SM_Object* sumoObj,
+ const STR_String& matname,
+ bool isDynamic,
+ bool isActor)
+{
+ PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+
+ // need easy access, not via 'node' etc.
+ KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic);
+ gameobj->SetPhysicsController(physicscontroller,isDynamic);
+
+
+ if (!gameobj->getClientInfo())
+ std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
+ physicscontroller->setNewClientInfo(gameobj->getClientInfo());
+
+
+ gameobj->GetSGNode()->AddSGController(physicscontroller);
+
+ gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
+
+ // store materialname in auxinfo, needed for touchsensors
+ gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
+
+ physicscontroller->SetObject(gameobj->GetSGNode());
+}
+
+static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
+{
+ // instance a mesh from a single vertex array & material
+ const RAS_TexVert *vertex_array = &darray->m_vertex[0];
+ DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
+
+ DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
+
+ std::vector<DT_Index> indices;
+ for (int p = 0; p < meshobj->NumPolygons(); p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ DT_Begin();
+ DT_VertexIndex(poly->GetVertexOffset(0));
+ DT_VertexIndex(poly->GetVertexOffset(1));
+ DT_VertexIndex(poly->GetVertexOffset(2));
+ DT_End();
+
+ // tesselate
+ if (poly->VertexCount() == 4)
+ {
+ DT_Begin();
+ DT_VertexIndex(poly->GetVertexOffset(0));
+ DT_VertexIndex(poly->GetVertexOffset(2));
+ DT_VertexIndex(poly->GetVertexOffset(3));
+ DT_End();
+ }
+ }
+ }
+
+ //DT_VertexIndices(indices.size(), &indices[0]);
+ DT_EndComplexShape();
+
+ map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
+ return shape;
+}
+
+static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
+{
+ // instance a mesh from a single vertex array & material
+ const RAS_TexVert *vertex_array = &darray->m_vertex[0];
+ DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
+
+ std::vector<DT_Index> indices;
+ for (int p = 0; p < meshobj->NumPolygons(); p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ indices.push_back(poly->GetVertexOffset(0));
+ indices.push_back(poly->GetVertexOffset(1));
+ indices.push_back(poly->GetVertexOffset(2));
+
+ if (poly->VertexCount() == 4)
+ indices.push_back(poly->GetVertexOffset(3));
+ }
+ }
+
+ DT_ShapeHandle shape = DT_NewPolytope(vertex_base);
+ DT_VertexIndices(indices.size(), &indices[0]);
+ DT_EndPolytope();
+
+ map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
+ return shape;
+}
+
+// This will have to be a method in a class somewhere...
+// Update SOLID with a changed physics mesh.
+// not used... yet.
+bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj)
+{
+ KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)];
+ if (instance)
+ {
+ const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0];
+ DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ());
+ return true;
+ }
+ return false;
+}
+
+static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
+{
+
+ DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
+ // Mesh has already been converted: reuse
+ if (shapeptr)
+ {
+ return *shapeptr;
+ }
+
+ // Mesh has no polygons!
+ int numpolys = meshobj->NumPolygons();
+ if (!numpolys)
+ {
+ return NULL;
+ }
+
+ // Count the number of collision polygons and check they all come from the same
+ // vertex array
+ int numvalidpolys = 0;
+ RAS_DisplayArray *darray = NULL;
+ RAS_IPolyMaterial *poly_material = NULL;
+ bool reinstance = true;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ // check polygon is from the same vertex array
+ if (poly->GetDisplayArray() != darray)
+ {
+ if (darray == NULL)
+ darray = poly->GetDisplayArray();
+ else
+ {
+ reinstance = false;
+ darray = NULL;
+ }
+ }
+
+ // check poly is from the same material
+ if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
+ {
+ if (poly_material)
+ {
+ reinstance = false;
+ poly_material = NULL;
+ }
+ else
+ poly_material = poly->GetMaterial()->GetPolyMaterial();
+ }
+
+ // count the number of collision polys
+ numvalidpolys++;
+
+ // We have one collision poly, and we can't reinstance, so we
+ // might as well break here.
+ if (!reinstance)
+ break;
+ }
+ }
+
+ // No collision polygons
+ if (numvalidpolys < 1)
+ return NULL;
+
+ DT_ShapeHandle shape;
+ if (reinstance)
+ {
+ if (polytope)
+ shape = InstancePhysicsPolytope(meshobj, darray, poly_material);
+ else
+ shape = InstancePhysicsComplex(meshobj, darray, poly_material);
+ }
+ else
+ {
+ if (polytope)
+ {
+ std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl;
+ if (!poly_material)
+ std::cout << " Check mesh materials." << std::endl;
+ if (darray == NULL)
+ std::cout << " Check number of vertices." << std::endl;
+ }
+
+ shape = DT_NewComplexShape(NULL);
+
+ numvalidpolys = 0;
+
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p2);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ { /* We have to tesselate here because SOLID can only raycast triangles */
+ DT_Begin();
+ /* V1, V2, V3 */
+ DT_Vertex(poly->GetVertex(2)->getXYZ());
+ DT_Vertex(poly->GetVertex(1)->getXYZ());
+ DT_Vertex(poly->GetVertex(0)->getXYZ());
+
+ numvalidpolys++;
+ DT_End();
+
+ if (poly->VertexCount() == 4)
+ {
+ DT_Begin();
+ /* V1, V3, V4 */
+ DT_Vertex(poly->GetVertex(3)->getXYZ());
+ DT_Vertex(poly->GetVertex(2)->getXYZ());
+ DT_Vertex(poly->GetVertex(0)->getXYZ());
+
+ numvalidpolys++;
+ DT_End();
+ }
+
+ }
+ }
+
+ DT_EndComplexShape();
+ }
+
+ if (numvalidpolys > 0)
+ {
+ map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
+ return shape;
+ }
+
+ delete shape;
+ return NULL;
+}
+
+void KX_ClearSumoSharedShapes()
+{
+ int numshapes = map_gamemesh_to_sumoshape.size();
+ int i;
+ for (i=0;i<numshapes ;i++)
+ {
+ DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
+ DT_DeleteShape(shape);
+ }
+
+ map_gamemesh_to_sumoshape.clear();
+
+ for (i=0; i < map_gamemesh_to_instance.size(); i++)
+ delete *map_gamemesh_to_instance.at(i);
+
+ map_gamemesh_to_instance.clear();
+}
+
+
+
+
+
+#endif //USE_SUMO_SOLID
+
+
+#ifdef USE_ODE
+
+void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop)
+{
+
+ // not yet, future extension :)
+ bool dyna=objprop->m_dyna;
+ bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
+ bool phantom = objprop->m_ghost;
+ class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+
+ class ODEPhysicsEnvironment* odeEnv =
+ (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+
+ dxSpace* space = odeEnv->GetOdeSpace();
+ dxWorld* world = odeEnv->GetOdeWorld();
+
+ bool isSphere = false;
+
+ switch (objprop->m_boundclass)
+ {
+ case KX_BOUNDBOX:
+ {
+
+ KX_OdePhysicsController* physicscontroller =
+ new KX_OdePhysicsController(
+ dyna,
+ fullRigidBody,
+ phantom,
+ motionstate,
+ space,
+ world,
+ shapeprops->m_mass,
+ smmaterial->m_friction,
+ smmaterial->m_restitution,
+ isSphere,
+ objprop->m_boundobject.box.m_center,
+ objprop->m_boundobject.box.m_extends,
+ objprop->m_boundobject.c.m_radius
+ );
+
+ gameobj->SetPhysicsController(physicscontroller);
+ physicscontroller->setNewClientInfo(gameobj->getClientInfo());
+ gameobj->GetSGNode()->AddSGController(physicscontroller);
+
+ bool isActor = objprop->m_isactor;
+ STR_String materialname;
+ if (meshobj)
+ materialname = meshobj->GetMaterialName(0);
+
+ const char* matname = materialname.ReadPtr();
+
+
+ physicscontroller->SetObject(gameobj->GetSGNode());
+
+ break;
+ }
+ default:
+ {
+ }
+ };
+
+}
+
+
+#endif // USE_ODE
+
+
#ifdef USE_BULLET
#include "CcdPhysicsEnvironment.h"
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
index 560c7fa4bb4..28bf12f5e87 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.cpp
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -49,8 +49,9 @@ KX_GameActuator::KX_GameActuator(SCA_IObject *gameobj,
const STR_String& filename,
const STR_String& loadinganimationname,
KX_Scene* scene,
- KX_KetsjiEngine* ketsjiengine)
- : SCA_IActuator(gameobj)
+ KX_KetsjiEngine* ketsjiengine,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T)
{
m_mode = mode;
m_filename = filename;
@@ -223,17 +224,26 @@ PyTypeObject KX_GameActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject KX_GameActuator::Parents[] =
+{
+ &KX_GameActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_GameActuator::Methods[] =
{
// Deprecated ----->
@@ -249,6 +259,21 @@ PyAttributeDef KX_GameActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_GameActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_GameActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
+
// Deprecated ----->
/* getFile */
const char KX_GameActuator::GetFile_doc[] =
@@ -257,7 +282,7 @@ const char KX_GameActuator::GetFile_doc[] =
PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds)
{
ShowDeprecationWarning("getFile()", "the fileName property");
- return PyUnicode_FromString(m_filename);
+ return PyString_FromString(m_filename);
}
/* setFile */
diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h
index cabbf827b40..b2b1d6ec2b9 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.h
+++ b/source/gameengine/Ketsji/KX_GameActuator.h
@@ -65,7 +65,8 @@ protected:
const STR_String& filename,
const STR_String& loadinganimationname,
KX_Scene* scene,
- KX_KetsjiEngine* ketsjiEngine);
+ KX_KetsjiEngine* ketsjiEngine,
+ PyTypeObject* T=&Type);
virtual ~KX_GameActuator();
virtual CValue* GetReplica();
@@ -76,6 +77,10 @@ protected:
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// Deprecated functions ----->
KX_PYMETHOD_DOC(KX_GameActuator,GetFile);
KX_PYMETHOD_DOC(KX_GameActuator,SetFile);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index bf80eec36d9..b266095c715 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -86,8 +86,10 @@ static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0,
KX_GameObject::KX_GameObject(
void* sgReplicationInfo,
- SG_Callbacks callbacks)
- : SCA_IObject(),
+ SG_Callbacks callbacks,
+ PyTypeObject* T
+) :
+ SCA_IObject(T),
m_bDyna(false),
m_layer(0),
m_pBlenderObject(NULL),
@@ -981,17 +983,7 @@ void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
GetSGNode()->SetLocalOrientation(rot);
}
-void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
-{
- // check on valid node in case a python controller holds a reference to a deleted object
- if (!GetSGNode())
- return;
- if (GetSGNode()->GetSGParent())
- GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
- else
- GetSGNode()->SetLocalOrientation(rot);
-}
void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
{
@@ -1070,13 +1062,7 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
return GetSGNode()->GetWorldOrientation();
}
-const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const
-{
- // check on valid node in case a python controller holds a reference to a deleted object
- if (!GetSGNode())
- return dummy_orientation;
- return GetSGNode()->GetLocalOrientation();
-}
+
const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
{
@@ -1087,14 +1073,7 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
return GetSGNode()->GetWorldScaling();
}
-const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const
-{
- // check on valid node in case a python controller holds a reference to a deleted object
- if (!GetSGNode())
- return dummy_scaling;
- return GetSGNode()->GetLocalScale();
-}
const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
{
@@ -1105,16 +1084,6 @@ const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
return dummy_point;
}
-const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
-{
- // check on valid node in case a python controller holds a reference to a deleted object
- if (GetSGNode())
- return GetSGNode()->GetLocalPosition();
- else
- return dummy_point;
-}
-
-
/* Suspend/ resume: for the dynamic behaviour, there is a simple
* method. For the residual motion, there is not. I wonder what the
* correct solution is for Sumo. Remove from the motion-update tree?
@@ -1182,181 +1151,6 @@ CListValue* KX_GameObject::GetChildrenRecursive()
return list;
}
-#ifdef USE_MATHUTILS
-
-/* These require an SGNode */
-#define MATHUTILS_VEC_CB_POS_LOCAL 1
-#define MATHUTILS_VEC_CB_POS_GLOBAL 2
-#define MATHUTILS_VEC_CB_SCALE_LOCAL 3
-#define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
-#define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
-
-static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_kxgameob_generic_check(PyObject *self_v)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- return 1;
-}
-
-static int mathutils_kxgameob_vector_get(PyObject *self_v, int subtype, float *vec_from)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- switch(subtype) {
- case MATHUTILS_VEC_CB_POS_LOCAL:
- self->NodeGetLocalPosition().getValue(vec_from);
- break;
- case MATHUTILS_VEC_CB_POS_GLOBAL:
- self->NodeGetWorldPosition().getValue(vec_from);
- break;
- case MATHUTILS_VEC_CB_SCALE_LOCAL:
- self->NodeGetLocalScaling().getValue(vec_from);
- break;
- case MATHUTILS_VEC_CB_SCALE_GLOBAL:
- self->NodeGetWorldScaling().getValue(vec_from);
- break;
- case MATHUTILS_VEC_CB_INERTIA_LOCAL:
- if(!self->GetPhysicsController()) return 0;
- self->GetPhysicsController()->GetLocalInertia().getValue(vec_from);
- break;
- }
-
- return 1;
-}
-
-static int mathutils_kxgameob_vector_set(PyObject *self_v, int subtype, float *vec_to)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- switch(subtype) {
- case MATHUTILS_VEC_CB_POS_LOCAL:
- self->NodeSetLocalPosition(MT_Point3(vec_to));
- self->NodeUpdateGS(0.f);
- break;
- case MATHUTILS_VEC_CB_POS_GLOBAL:
- self->NodeSetWorldPosition(MT_Point3(vec_to));
- self->NodeUpdateGS(0.f);
- break;
- case MATHUTILS_VEC_CB_SCALE_LOCAL:
- self->NodeSetLocalScale(MT_Point3(vec_to));
- self->NodeUpdateGS(0.f);
- break;
- case MATHUTILS_VEC_CB_SCALE_GLOBAL:
- break;
- case MATHUTILS_VEC_CB_INERTIA_LOCAL:
- /* read only */
- break;
- }
-
- return 1;
-}
-
-static int mathutils_kxgameob_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
-{
- float f[4];
- /* lazy, avoid repeteing the case statement */
- if(!mathutils_kxgameob_vector_get(self_v, subtype, f))
- return 0;
-
- vec_from[index]= f[index];
- return 1;
-}
-
-static int mathutils_kxgameob_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
-{
- float f= vec_to[index];
-
- /* lazy, avoid repeteing the case statement */
- if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to))
- return 0;
-
- vec_to[index]= f;
- mathutils_kxgameob_vector_set(self_v, subtype, vec_to);
-
- return 1;
-}
-
-Mathutils_Callback mathutils_kxgameob_vector_cb = {
- mathutils_kxgameob_generic_check,
- mathutils_kxgameob_vector_get,
- mathutils_kxgameob_vector_set,
- mathutils_kxgameob_vector_get_index,
- mathutils_kxgameob_vector_set_index
-};
-
-/* Matrix */
-#define MATHUTILS_MAT_CB_ORI_LOCAL 1
-#define MATHUTILS_MAT_CB_ORI_GLOBAL 2
-
-static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_kxgameob_matrix_get(PyObject *self_v, int subtype, float *mat_from)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- switch(subtype) {
- case MATHUTILS_MAT_CB_ORI_LOCAL:
- self->NodeGetLocalOrientation().getValue3x3(mat_from);
- break;
- case MATHUTILS_MAT_CB_ORI_GLOBAL:
- self->NodeGetWorldOrientation().getValue3x3(mat_from);
- break;
- }
-
- return 1;
-}
-
-
-static int mathutils_kxgameob_matrix_set(PyObject *self_v, int subtype, float *mat_to)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- MT_Matrix3x3 mat3x3;
- switch(subtype) {
- case MATHUTILS_MAT_CB_ORI_LOCAL:
- mat3x3.setValue3x3(mat_to);
- self->NodeSetLocalOrientation(mat3x3);
- self->NodeUpdateGS(0.f);
- break;
- case MATHUTILS_MAT_CB_ORI_GLOBAL:
- mat3x3.setValue3x3(mat_to);
- self->NodeSetLocalOrientation(mat3x3);
- self->NodeUpdateGS(0.f);
- break;
- }
-
- return 1;
-}
-
-Mathutils_Callback mathutils_kxgameob_matrix_cb = {
- mathutils_kxgameob_generic_check,
- mathutils_kxgameob_matrix_get,
- mathutils_kxgameob_matrix_set,
- NULL,
- NULL
-};
-
-
-void KX_GameObject_Mathutils_Callback_Init(void)
-{
- // register mathutils callbacks, ok to run more then once.
- mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
- mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
-}
-
-#endif // USE_MATHUTILS
/* ------- python stuff ---------------------------------------------------*/
@@ -1496,7 +1290,7 @@ PyObject* KX_GameObject::PyGetPosition()
static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
{
KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- const char *attr_str= _PyUnicode_AsString(item);
+ const char *attr_str= PyString_AsString(item);
CValue* resultattr;
PyObject* pyconvert;
@@ -1530,7 +1324,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
{
KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
- const char *attr_str= _PyUnicode_AsString(key);
+ const char *attr_str= PyString_AsString(key);
if(attr_str==NULL)
PyErr_Clear();
@@ -1562,7 +1356,7 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
int set= 0;
/* as CValue */
- if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
+ if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
{
CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
@@ -1624,7 +1418,7 @@ static int Seq_Contains(PyObject *self_v, PyObject *value)
return -1;
}
- if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value)))
+ if(PyString_Check(value) && self->GetProperty(PyString_AsString(value)))
return 1;
if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
@@ -1672,23 +1466,30 @@ PyTypeObject KX_GameObject::Type = {
&Sequence,
&Mapping,
0,0,0,
- NULL,
- NULL,
+ py_base_getattro,
+ py_base_setattro,
0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ Py_TPFLAGS_DEFAULT,
0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+
+
+
+PyParentObject KX_GameObject::Parents[] = {
+ &KX_GameObject::Type,
&SCA_IObject::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &CValue::Type,
+ NULL
};
PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- return PyUnicode_FromString(self->GetName().ReadPtr());
+ return PyString_FromString(self->GetName().ReadPtr());
}
PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1795,11 +1596,7 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-#ifdef USE_MATHUTILS
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
-#else
return PyObjectFrom(self->NodeGetWorldPosition());
-#endif
}
int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1817,11 +1614,10 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-#ifdef USE_MATHUTILS
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
-#else
- return PyObjectFrom(self->NodeGetLocalPosition());
-#endif
+ if (self->GetSGNode())
+ return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
+ else
+ return PyObjectFrom(dummy_point);
}
int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1839,23 +1635,17 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-#ifdef USE_MATHUTILS
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
-#else
if (self->GetPhysicsController())
+ {
return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
+ }
return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
-#endif
}
PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
-#ifdef USE_MATHUTILS
- return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
-#else
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldOrientation());
-#endif
}
int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1867,7 +1657,12 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
return PY_SET_ATTR_FAIL;
- self->NodeSetGlobalOrientation(rot);
+ if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
+ self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
+ }
+ else {
+ self->NodeSetLocalOrientation(rot);
+ }
self->NodeUpdateGS(0.f);
return PY_SET_ATTR_SUCCESS;
@@ -1875,12 +1670,11 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
-#ifdef USE_MATHUTILS
- return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
-#else
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- return PyObjectFrom(self->NodeGetLocalOrientation());
-#endif
+ if (self->GetSGNode())
+ return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
+ else
+ return PyObjectFrom(dummy_orientation);
}
int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1900,21 +1694,16 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-#ifdef USE_MATHUTILS
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
-#else
return PyObjectFrom(self->NodeGetWorldScaling());
-#endif
}
PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-#ifdef USE_MATHUTILS
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
-#else
- return PyObjectFrom(self->NodeGetLocalScaling());
-#endif
+ if (self->GetSGNode())
+ return PyObjectFrom(self->GetSGNode()->GetLocalScale());
+ else
+ return PyObjectFrom(dummy_scaling);
}
int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1961,13 +1750,13 @@ PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
int state = 0;
state |= self->GetState();
- return PyLong_FromSsize_t(state);
+ return PyInt_FromLong(state);
}
int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- int state_i = PyLong_AsSsize_t(value);
+ int state_i = PyInt_AsLong(value);
unsigned int state = 0;
if (state_i == -1 && PyErr_Occurred()) {
@@ -2038,6 +1827,128 @@ PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_
return self->m_attr_dict;
}
+/* We need these because the macros have a return in them */
+PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
+{
+ py_getattro_up(SCA_IObject);
+}
+
+int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method
+{
+ py_setattro_up(SCA_IObject);
+}
+
+
+PyObject* KX_GameObject::py_getattro(PyObject *attr)
+{
+ PyObject *object= py_getattro__internal(attr);
+
+ if (object==NULL && m_attr_dict)
+ {
+ /* backup the exception incase the attr doesnt exist in the dict either */
+ PyObject *err_type, *err_value, *err_tb;
+ PyErr_Fetch(&err_type, &err_value, &err_tb);
+
+ object= PyDict_GetItem(m_attr_dict, attr);
+ if (object) {
+ Py_INCREF(object);
+
+ PyErr_Clear();
+ Py_XDECREF( err_type );
+ Py_XDECREF( err_value );
+ Py_XDECREF( err_tb );
+ }
+ else {
+ PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
+ }
+ }
+ return object;
+}
+
+PyObject* KX_GameObject::py_getattro_dict() {
+ //py_getattro_dict_up(SCA_IObject);
+ PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
+ if(dict==NULL)
+ return NULL;
+
+ /* normally just return this but KX_GameObject has some more items */
+
+
+ /* Not super fast getting as a list then making into dict keys but its only for dir() */
+ PyObject *list= ConvertKeysToPython();
+ if(list)
+ {
+ int i;
+ for(i=0; i<PyList_Size(list); i++)
+ PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
+ }
+ else
+ PyErr_Clear();
+
+ Py_DECREF(list);
+
+ /* Add m_attr_dict if we have it */
+ if(m_attr_dict)
+ PyDict_Update(dict, m_attr_dict);
+
+ return dict;
+}
+
+int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
+{
+ int ret= py_setattro__internal(attr, value);
+
+ if (ret==PY_SET_ATTR_SUCCESS) {
+ /* remove attribute in our own dict to avoid double ups */
+ /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
+ if (m_attr_dict) {
+ if (PyDict_DelItem(m_attr_dict, attr) != 0)
+ PyErr_Clear();
+ }
+ }
+
+ if (ret==PY_SET_ATTR_COERCE_FAIL) {
+ /* CValue attribute exists, remove CValue and add PyDict value */
+ RemoveProperty(PyString_AsString(attr));
+ ret= PY_SET_ATTR_MISSING;
+ }
+
+ if (ret==PY_SET_ATTR_MISSING) {
+ /* Lazy initialization */
+ if (m_attr_dict==NULL)
+ m_attr_dict = PyDict_New();
+
+ if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
+ PyErr_Clear();
+ ret= PY_SET_ATTR_SUCCESS;
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
+ ret= PY_SET_ATTR_FAIL;
+ }
+ }
+
+ return ret;
+}
+
+
+int KX_GameObject::py_delattro(PyObject *attr)
+{
+ ShowDeprecationWarning("del ob.attr", "del ob['attr'] for user defined properties");
+
+ char *attr_str= PyString_AsString(attr);
+
+ if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
+ return PY_SET_ATTR_SUCCESS;
+
+ if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
+ return PY_SET_ATTR_SUCCESS;
+
+ PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
+ return PY_SET_ATTR_MISSING;
+}
+
+
PyObject* KX_GameObject::PyApplyForce(PyObject* args)
{
int local = 0;
@@ -2181,7 +2092,7 @@ PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
PyObject* KX_GameObject::PyGetVisible()
{
ShowDeprecationWarning("getVisible()", "the visible property");
- return PyLong_FromSsize_t(m_bVisible);
+ return PyInt_FromLong(m_bVisible);
}
PyObject* KX_GameObject::PyGetState()
@@ -2189,13 +2100,13 @@ PyObject* KX_GameObject::PyGetState()
ShowDeprecationWarning("getState()", "the state property");
int state = 0;
state |= GetState();
- return PyLong_FromSsize_t(state);
+ return PyInt_FromLong(state);
}
PyObject* KX_GameObject::PySetState(PyObject* value)
{
ShowDeprecationWarning("setState()", "the state property");
- int state_i = PyLong_AsSsize_t(value);
+ int state_i = PyInt_AsLong(value);
unsigned int state = 0;
if (state_i == -1 && PyErr_Occurred()) {
@@ -2501,7 +2412,7 @@ PyObject* KX_GameObject::PyGetPhysicsId()
{
physid= (uint_ptr)ctrl->GetUserData();
}
- return PyLong_FromSsize_t((long)physid);
+ return PyInt_FromLong((long)physid);
}
PyObject* KX_GameObject::PyGetPropertyNames()
@@ -2877,8 +2788,8 @@ PyObject* KX_GameObject::Pyget(PyObject *args)
return NULL;
- if(PyUnicode_Check(key)) {
- CValue *item = GetProperty(_PyUnicode_AsString(key));
+ if(PyString_Check(key)) {
+ CValue *item = GetProperty(PyString_AsString(key));
if (item) {
ret = item->ConvertValueToPython();
if(ret)
@@ -2947,13 +2858,13 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
}
}
- if (PyUnicode_Check(value)) {
- *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) ));
+ if (PyString_Check(value)) {
+ *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
if (*object) {
return true;
} else {
- PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value));
+ PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
return false;
}
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 947cc9959ff..ff5c8a01e6e 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -63,10 +63,6 @@ struct Object;
/* utility conversion function */
bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix);
-#ifdef USE_MATHUTILS
-void KX_GameObject_Mathutils_Callback_Init(void);
-#endif
-
/**
* KX_GameObject is the main class for dynamic objects.
*/
@@ -189,7 +185,8 @@ public:
KX_GameObject(
void* sgReplicationInfo,
- SG_Callbacks callbacks
+ SG_Callbacks callbacks,
+ PyTypeObject* T=&Type
);
virtual
@@ -396,7 +393,6 @@ public:
void NodeSetLocalPosition(const MT_Point3& trans );
void NodeSetLocalOrientation(const MT_Matrix3x3& rot );
- void NodeSetGlobalOrientation(const MT_Matrix3x3& rot );
void NodeSetLocalScale( const MT_Vector3& scale );
@@ -410,13 +406,21 @@ public:
double time
);
- const MT_Matrix3x3& NodeGetWorldOrientation( ) const;
- const MT_Vector3& NodeGetWorldScaling( ) const;
- const MT_Point3& NodeGetWorldPosition( ) const;
+ const
+ MT_Matrix3x3&
+ NodeGetWorldOrientation(
+ ) const;
+
+ const
+ MT_Vector3&
+ NodeGetWorldScaling(
+ ) const;
+
+ const
+ MT_Point3&
+ NodeGetWorldPosition(
+ ) const;
- const MT_Matrix3x3& NodeGetLocalOrientation( ) const;
- const MT_Vector3& NodeGetLocalScaling( ) const;
- const MT_Point3& NodeGetLocalPosition( ) const;
/**
* @section scene graph node accessor functions.
@@ -807,10 +811,22 @@ public:
/**
* @section Python interface functions.
*/
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method
+ virtual int py_delattro(PyObject *attr);
virtual PyObject* py_repr(void)
{
- return PyUnicode_FromString(GetName().ReadPtr());
+ return PyString_FromString(GetName().ReadPtr());
}
+
+
+ /* quite annoying that we need these but the bloody
+ * py_getattro_up and py_setattro_up macro's have a returns in them! */
+ PyObject* py_getattro__internal(PyObject *attr);
+ int py_setattro__internal(PyObject *attr, PyObject *value); // py_setattro method
+
KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition);
KX_PYMETHOD_O(KX_GameObject,SetPosition);
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index 73a370a1681..3ec0598ac03 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -70,8 +70,9 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
int acttype,
bool ipo_as_force,
bool ipo_add,
- bool ipo_local)
- : SCA_IActuator(gameobj),
+ bool ipo_local,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj,T),
m_bNegativeEvent(false),
m_startframe (starttime),
m_endframe(endtime),
@@ -428,15 +429,19 @@ PyTypeObject KX_IpoActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_IpoActuator::Parents[] = {
+ &KX_IpoActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_IpoActuator::Methods[] = {
@@ -472,6 +477,18 @@ PyAttributeDef KX_IpoActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_IpoActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_IpoActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
+{
+ py_setattro_up(SCA_IActuator);
+}
/* set --------------------------------------------------------------------- */
const char KX_IpoActuator::Set_doc[] =
@@ -672,7 +689,7 @@ const char KX_IpoActuator::GetType_doc[] =
"\tReturns the operation mode of the actuator.\n";
PyObject* KX_IpoActuator::PyGetType() {
ShowDeprecationWarning("getType()", "the mode property");
- return PyLong_FromSsize_t(m_type);
+ return PyInt_FromLong(m_type);
}
/* 10. setForceIpoActsLocal: */
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
index 01051ca82dc..9ea597def1e 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.h
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -121,7 +121,8 @@ public:
int acttype,
bool ipo_as_force,
bool ipo_add,
- bool ipo_local);
+ bool ipo_local,
+ PyTypeObject* T=&Type);
virtual ~KX_IpoActuator() {};
virtual CValue* GetReplica() {
@@ -137,6 +138,10 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
//KX_PYMETHOD_DOC
KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,Set);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index cc0f50d9e7a..a43ea59220b 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -61,6 +61,10 @@
#include "KX_PyConstraintBinding.h"
#include "PHY_IPhysicsEnvironment.h"
+#ifdef USE_SUMO_SOLID
+#include "SumoPhysicsEnvironment.h"
+#endif
+
#include "SND_Scene.h"
#include "SND_IAudioDevice.h"
@@ -396,9 +400,9 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
World* world = m_scenes[0]->GetBlenderScene()->world;
if (world)
{
- m_ticrate = world->ticrate ? world->ticrate : DEFAULT_LOGIC_TIC_RATE;
- m_maxLogicFrame = world->maxlogicstep ? world->maxlogicstep : 5;
- m_maxPhysicsFrame = world->maxphystep ? world->maxlogicstep : 5;
+ m_ticrate = world->ticrate;
+ m_maxLogicFrame = world->maxlogicstep;
+ m_maxPhysicsFrame = world->maxphystep;
}
else
{
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index fb385f8a9a2..ae9e097a96e 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -51,9 +51,12 @@
KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
class RAS_IRenderTools* rendertools,
const RAS_LightObject& lightobj,
- bool glsl)
- : KX_GameObject(sgReplicationInfo,callbacks),
- m_rendertools(rendertools)
+ bool glsl,
+ PyTypeObject* T
+ )
+ :
+ KX_GameObject(sgReplicationInfo,callbacks,T),
+ m_rendertools(rendertools)
{
m_lightobj = lightobj;
m_lightobj.m_scene = sgReplicationInfo;
@@ -268,6 +271,11 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
/* Python Integration Hooks */
/* ------------------------------------------------------------------------- */
+PyObject* KX_LightObject::py_getattro_dict() {
+ py_getattro_dict_up(KX_GameObject);
+}
+
+
PyTypeObject KX_LightObject::Type = {
#if (PY_VERSION_HEX >= 0x02060000)
PyVarObject_HEAD_INIT(NULL, 0)
@@ -289,17 +297,20 @@ PyTypeObject KX_LightObject::Type = {
&KX_GameObject::Sequence,
&KX_GameObject::Mapping,
0,0,0,
- NULL,
- NULL,
+ py_base_getattro,
+ py_base_setattro,
0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ Py_TPFLAGS_DEFAULT,
0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &KX_GameObject::Type,
- 0,0,0,0,0,0,
- py_base_new
+ Methods
+};
+
+PyParentObject KX_LightObject::Parents[] = {
+ &KX_LightObject::Type,
+ &KX_GameObject::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_LightObject::Methods[] = {
@@ -351,11 +362,11 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT
const char* type = attrdef->m_name;
if(strcmp(type, "SPOT")) {
- retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT);
+ retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SPOT);
} else if (strcmp(type, "SUN")) {
- retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN);
+ retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SUN);
} else if (strcmp(type, "NORMAL")) {
- retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL);
+ retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL);
}
return retvalue;
@@ -364,13 +375,13 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT
PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
- return PyLong_FromSsize_t(self->m_lightobj.m_type);
+ return PyInt_FromLong(self->m_lightobj.m_type);
}
int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
- int val = PyLong_AsSsize_t(value);
+ int val = PyInt_AsLong(value);
if((val==-1 && PyErr_Occurred()) || val<0 || val>2) {
PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2");
return PY_SET_ATTR_FAIL;
@@ -390,3 +401,14 @@ int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attr
return PY_SET_ATTR_SUCCESS;
}
+
+
+PyObject* KX_LightObject::py_getattro(PyObject *attr)
+{
+ py_getattro_up(KX_GameObject);
+}
+
+int KX_LightObject::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(KX_GameObject);
+}
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 0b7ccbe81ab..358c705080a 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -49,7 +49,7 @@ protected:
Scene* m_blenderscene;
public:
- KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl);
+ KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type);
virtual ~KX_LightObject();
virtual CValue* GetReplica();
RAS_LightObject* GetLightData() { return &m_lightobj;}
@@ -64,6 +64,10 @@ public:
void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans);
void UnbindShadowBuffer(class RAS_IRasterizer *ras);
void Update();
+
+ virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
/* attributes */
static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index 96e8f61e4c8..11effa1ca98 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -62,15 +62,18 @@ PyTypeObject KX_MeshProxy::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_MeshProxy::Parents[] = {
+ &KX_MeshProxy::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &PyObjectPlus::Type,
+ NULL
};
PyMethodDef KX_MeshProxy::Methods[] = {
@@ -103,8 +106,24 @@ void KX_MeshProxy::SetMeshModified(bool v)
m_meshobj->SetMeshModified(v);
}
+
+PyObject* KX_MeshProxy::py_getattro(PyObject *attr)
+{
+ py_getattro_up(CValue);
+}
+
+PyObject* KX_MeshProxy::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
+
+int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(CValue);
+}
+
+
KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh)
- : CValue(), m_meshobj(mesh)
+ : CValue(&Type), m_meshobj(mesh)
{
}
@@ -131,14 +150,14 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds)
{
int num = m_meshobj->NumMaterials();
ShowDeprecationWarning("getNumMaterials()", "the numMaterials property");
- return PyLong_FromSsize_t(num);
+ return PyInt_FromLong(num);
}
PyObject* KX_MeshProxy::PyGetNumPolygons()
{
int num = m_meshobj->NumPolygons();
ShowDeprecationWarning("getNumPolygons()", "the numPolygons property");
- return PyLong_FromSsize_t(num);
+ return PyInt_FromLong(num);
}
PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
@@ -154,7 +173,7 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
return NULL;
}
- return PyUnicode_FromString(matname.Ptr());
+ return PyString_FromString(matname.Ptr());
}
@@ -172,7 +191,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
return NULL;
}
- return PyUnicode_FromString(matname.Ptr());
+ return PyString_FromString(matname.Ptr());
}
@@ -195,7 +214,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
length = m_meshobj->NumVertices(mat);
}
- return PyLong_FromSsize_t(length);
+ return PyInt_FromLong(length);
}
@@ -285,12 +304,12 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_
PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
- return PyLong_FromSsize_t(self->m_meshobj->NumMaterials());
+ return PyInt_FromLong(self->m_meshobj->NumMaterials());
}
PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
- return PyLong_FromSsize_t(self->m_meshobj->NumPolygons());
+ return PyInt_FromLong(self->m_meshobj->NumPolygons());
}
/* a close copy of ConvertPythonToGameObject but for meshes */
@@ -313,13 +332,13 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none
}
}
- if (PyUnicode_Check(value)) {
- *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( _PyUnicode_AsString(value) ));
+ if (PyString_Check(value)) {
+ *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) ));
if (*object) {
return true;
} else {
- PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, _PyUnicode_AsString(value));
+ PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value));
return false;
}
}
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
index 4b6543677ad..bfdd4be4118 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.h
+++ b/source/gameengine/Ketsji/KX_MeshProxy.h
@@ -56,6 +56,9 @@ public:
virtual CValue* GetReplica();
// stuff for python integration
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); // Deprecated
KX_PYMETHOD(KX_MeshProxy,GetMaterialName);
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index ba4b47cb03f..fde10a493db 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -63,8 +63,9 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
int focusmode,
KX_Scene* kxscene,
KX_KetsjiEngine *kxengine,
- SCA_IObject* gameobj)
- : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T),
m_focusmode(focusmode),
m_kxscene(kxscene),
m_kxengine(kxengine)
@@ -355,15 +356,20 @@ PyTypeObject KX_MouseFocusSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_MouseFocusSensor::Parents[] = {
+ &KX_MouseFocusSensor::Type,
&SCA_MouseSensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_MouseFocusSensor::Methods[] = {
@@ -387,6 +393,15 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_MouseSensor);
+}
+
+PyObject* KX_MouseFocusSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_MouseSensor);
+}
+
+
const char KX_MouseFocusSensor::GetHitObject_doc[] =
"getHitObject()\n"
"\tReturns the object that was hit by this ray.\n";
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index dfada7a59cc..29d674eb305 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -56,7 +56,8 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
int focusmode,
KX_Scene* kxscene,
KX_KetsjiEngine* kxengine,
- SCA_IObject* gameobj);
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
virtual ~KX_MouseFocusSensor() { ; };
virtual CValue* GetReplica() {
@@ -88,6 +89,8 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget);
KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource);
diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp
index 1a211a64b35..44842b7f5b3 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.cpp
+++ b/source/gameengine/Ketsji/KX_NearSensor.cpp
@@ -48,13 +48,15 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
bool bFindMaterial,
const STR_String& touchedpropname,
class KX_Scene* scene,
- PHY_IPhysicsController* ctrl)
+ PHY_IPhysicsController* ctrl,
+ PyTypeObject* T)
:KX_TouchSensor(eventmgr,
gameobj,
bFindMaterial,
false,
- touchedpropname
- /*, scene */),
+ touchedpropname,
+ /* scene, */
+ T),
m_Margin(margin),
m_ResetMargin(resetmargin)
@@ -270,17 +272,26 @@ PyTypeObject KX_NearSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject KX_NearSensor::Parents[] = {
+ &KX_NearSensor::Type,
&KX_TouchSensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_NearSensor::Methods[] = {
//No methods
{NULL,NULL} //Sentinel
@@ -291,3 +302,18 @@ PyAttributeDef KX_NearSensor::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance),
{NULL} //Sentinel
};
+
+
+PyObject* KX_NearSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(KX_TouchSensor);
+}
+
+PyObject* KX_NearSensor::py_getattro_dict() {
+ py_getattro_dict_up(KX_TouchSensor);
+}
+
+int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value)
+{
+ py_setattro_up(KX_TouchSensor);
+}
diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h
index f3c1d74805c..63099e181a0 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.h
+++ b/source/gameengine/Ketsji/KX_NearSensor.h
@@ -54,7 +54,8 @@ public:
bool bFindMaterial,
const STR_String& touchedpropname,
class KX_Scene* scene,
- PHY_IPhysicsController* ctrl);
+ PHY_IPhysicsController* ctrl,
+ PyTypeObject* T=&Type);
/*
public:
KX_NearSensor(class SCA_EventManager* eventmgr,
@@ -63,7 +64,8 @@ public:
double resetmargin,
bool bFindMaterial,
const STR_String& touchedpropname,
- class KX_Scene* scene);
+ class KX_Scene* scene,
+ PyTypeObject* T=&Type);
*/
virtual ~KX_NearSensor();
virtual void SynchronizeTransform();
@@ -81,6 +83,9 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
//No methods
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index ae340d12be4..eaae04d406d 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -53,9 +53,10 @@ KX_ObjectActuator(
const MT_Vector3& linV,
const MT_Vector3& angV,
const short damping,
- const KX_LocalFlags& flag
+ const KX_LocalFlags& flag,
+ PyTypeObject* T
) :
- SCA_IActuator(gameobj),
+ SCA_IActuator(gameobj,T),
m_force(force),
m_torque(torque),
m_dloc(dloc),
@@ -341,15 +342,19 @@ PyTypeObject KX_ObjectActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_ObjectActuator::Parents[] = {
+ &KX_ObjectActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_ObjectActuator::Methods[] = {
@@ -391,14 +396,9 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = {
KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc),
KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot),
-#ifdef USE_MATHUTILS
- KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV),
- KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV),
-#else
KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags),
- KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
-#endif
KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity),
+ KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity),
KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping),
KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX),
@@ -409,130 +409,21 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = {
{ NULL } //Sentinel
};
-/* Attribute get/set functions */
-
-#ifdef USE_MATHUTILS
-
-/* These require an SGNode */
-#define MATHUTILS_VEC_CB_LINV 1
-#define MATHUTILS_VEC_CB_ANGV 2
-
-static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_obactu_generic_check(PyObject *self_v)
-{
- KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- return 1;
-}
-
-static int mathutils_obactu_vector_get(PyObject *self_v, int subtype, float *vec_from)
-{
- KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- switch(subtype) {
- case MATHUTILS_VEC_CB_LINV:
- self->m_linear_velocity.getValue(vec_from);
- break;
- case MATHUTILS_VEC_CB_ANGV:
- self->m_angular_velocity.getValue(vec_from);
- break;
- }
-
- return 1;
-}
-
-static int mathutils_obactu_vector_set(PyObject *self_v, int subtype, float *vec_to)
-{
- KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
- if(self==NULL)
- return 0;
-
- switch(subtype) {
- case MATHUTILS_VEC_CB_LINV:
- self->m_linear_velocity.setValue(vec_to);
- break;
- case MATHUTILS_VEC_CB_ANGV:
- self->m_angular_velocity.setValue(vec_to);
- break;
- }
-
- return 1;
-}
-
-static int mathutils_obactu_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
-{
- float f[4];
- /* lazy, avoid repeteing the case statement */
- if(!mathutils_obactu_vector_get(self_v, subtype, f))
- return 0;
-
- vec_from[index]= f[index];
- return 1;
-}
-
-static int mathutils_obactu_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
-{
- float f= vec_to[index];
-
- /* lazy, avoid repeteing the case statement */
- if(!mathutils_obactu_vector_get(self_v, subtype, vec_to))
- return 0;
-
- vec_to[index]= f;
- mathutils_obactu_vector_set(self_v, subtype, vec_to);
-
- return 1;
-}
-
-Mathutils_Callback mathutils_obactu_vector_cb = {
- mathutils_obactu_generic_check,
- mathutils_obactu_vector_get,
- mathutils_obactu_vector_set,
- mathutils_obactu_vector_get_index,
- mathutils_obactu_vector_set_index
-};
-
-PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
-{
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
+PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
}
-int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
-{
- KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
- if (!PyVecTo(value, self->m_linear_velocity))
- return PY_SET_ATTR_FAIL;
-
- return PY_SET_ATTR_SUCCESS;
-}
-
-PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
-{
- return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
-}
-
-int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
-{
- KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
- if (!PyVecTo(value, self->m_angular_velocity))
- return PY_SET_ATTR_FAIL;
- return PY_SET_ATTR_SUCCESS;
+PyObject* KX_ObjectActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
}
-
-void KX_ObjectActuator_Mathutils_Callback_Init(void)
+int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value)
{
- // register mathutils callbacks, ok to run more then once.
- mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb);
+ py_setattro_up(SCA_IActuator);
}
-#endif // USE_MATHUTILS
+/* Attribute get/set functions */
PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -555,7 +446,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE
{
self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
- self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+ self->m_bitLocalFlag.Torque = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
if (!PyErr_Occurred())
{
@@ -591,7 +482,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE
{
self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
- self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+ self->m_bitLocalFlag.DLoc = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
if (!PyErr_Occurred())
{
@@ -627,7 +518,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE
{
self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
- self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+ self->m_bitLocalFlag.DRot = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
if (!PyErr_Occurred())
{
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
index 20aec9e0e86..f9bd2a0c748 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -35,10 +35,6 @@
#include "SCA_IActuator.h"
#include "MT_Vector3.h"
-#ifdef USE_MATHUTILS
-void KX_ObjectActuator_Mathutils_Callback_Init(void);
-#endif
-
class KX_GameObject;
//
@@ -135,7 +131,8 @@ public:
const MT_Vector3& linV,
const MT_Vector3& angV,
const short damping,
- const KX_LocalFlags& flag
+ const KX_LocalFlags& flag,
+ PyTypeObject* T=&Type
);
~KX_ObjectActuator();
CValue* GetReplica();
@@ -162,6 +159,10 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce);
KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce);
@@ -196,13 +197,6 @@ public:
static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-#ifdef USE_MATHUTILS
- static PyObject* pyattr_get_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-#endif
-
// This lets the attribute macros use UpdateFuzzyFlags()
static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef)
{
diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp
new file mode 100644
index 00000000000..dc6990267d4
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp
@@ -0,0 +1,257 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "KX_ConvertPhysicsObject.h"
+
+#ifdef USE_ODE
+
+#include "KX_OdePhysicsController.h"
+#include "KX_GameObject.h"
+#include "KX_MotionState.h"
+
+#include "MT_assert.h"
+
+#include "PHY_IPhysicsEnvironment.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+KX_OdePhysicsController::KX_OdePhysicsController(
+ bool dyna,
+ bool fullRigidBody,
+ bool phantom,
+ class PHY_IMotionState* motionstate,
+ struct dxSpace* space,
+ struct dxWorld* world,
+ float mass,
+ float friction,
+ float restitution,
+ bool implicitsphere,
+ float center[3],
+ float extends[3],
+ float radius
+ )
+: KX_IPhysicsController(dyna,false,(PHY_IPhysicsController*)this),
+ODEPhysicsController(
+dyna,fullRigidBody,phantom,motionstate,
+space,world,mass,friction,restitution,
+implicitsphere,center,extends,radius)
+{
+};
+
+
+bool KX_OdePhysicsController::Update(double time)
+{
+ return SynchronizeMotionStates(time);
+}
+
+void KX_OdePhysicsController::SetObject (SG_IObject* object)
+{
+ SG_Controller::SetObject(object);
+
+ // cheating here...
+ KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject();
+ gameobj->SetPhysicsController(this);
+
+}
+
+
+
+void KX_OdePhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)
+{
+ ODEPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]);
+}
+
+
+
+void KX_OdePhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local)
+{
+ ODEPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local);
+
+}
+void KX_OdePhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
+{
+ double oldmat[12];
+ drot.getValue(oldmat);
+ float newmat[9];
+ float *m = &newmat[0];
+ double *orgm = &oldmat[0];
+
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+
+ ODEPhysicsController::RelativeRotate(newmat,local);
+
+}
+
+void KX_OdePhysicsController::ApplyTorque(const MT_Vector3& torque,bool local)
+{
+ ODEPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local);
+
+}
+void KX_OdePhysicsController::ApplyForce(const MT_Vector3& force,bool local)
+{
+ ODEPhysicsController::ApplyForce(force[0],force[1],force[2],local);
+
+}
+MT_Vector3 KX_OdePhysicsController::GetLinearVelocity()
+{
+ return MT_Vector3(0,0,0);
+}
+
+MT_Vector3 KX_OdePhysicsController::GetVelocity(const MT_Point3& pos)
+{
+ return MT_Vector3(0,0,0);
+}
+
+void KX_OdePhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
+{
+
+}
+void KX_OdePhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local)
+{
+ ODEPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local);
+}
+
+void KX_OdePhysicsController::setOrientation(const MT_Matrix3x3& rot)
+{
+ MT_Quaternion orn = rot.getRotation();
+ ODEPhysicsController::setOrientation(orn[0],orn[1],orn[2],orn[3]);
+}
+
+void KX_OdePhysicsController::getOrientation(MT_Quaternion& orn)
+{
+ float florn[4];
+ florn[0]=orn[0];
+ florn[1]=orn[1];
+ florn[2]=orn[2];
+ florn[3]=orn[3];
+ ODEPhysicsController::getOrientation(florn[0],florn[1],florn[2],florn[3]);
+ orn[0] = florn[0];
+ orn[1] = florn[1];
+ orn[2] = florn[2];
+ orn[3] = florn[3];
+
+
+}
+
+void KX_OdePhysicsController::setPosition(const MT_Point3& pos)
+{
+ ODEPhysicsController::setPosition(pos[0],pos[1],pos[2]);
+}
+
+void KX_OdePhysicsController::setScaling(const MT_Vector3& scaling)
+{
+}
+
+MT_Scalar KX_OdePhysicsController::GetMass()
+{
+ return ODEPhysicsController::getMass();
+}
+
+MT_Scalar KX_OdePhysicsController::GetRadius()
+{
+ return MT_Scalar(0.f);
+}
+
+MT_Vector3 KX_OdePhysicsController::getReactionForce()
+{
+ return MT_Vector3(0,0,0);
+}
+void KX_OdePhysicsController::setRigidBody(bool rigid)
+{
+
+}
+
+void KX_OdePhysicsController::SuspendDynamics(bool)
+{
+ ODEPhysicsController::SuspendDynamics();
+}
+void KX_OdePhysicsController::RestoreDynamics()
+{
+ ODEPhysicsController::RestoreDynamics();
+}
+
+
+SG_Controller* KX_OdePhysicsController::GetReplica(class SG_Node* destnode)
+{
+ PHY_IMotionState* motionstate = new KX_MotionState(destnode);
+ KX_OdePhysicsController* copyctrl = new KX_OdePhysicsController(*this);
+
+ // nlin: copied from KX_SumoPhysicsController.cpp. Not 100% sure what this does....
+ // furthermore, the parentctrl is not used in ODEPhysicsController::PostProcessReplica, but
+ // maybe it can/should be used in the future...
+
+ // begin copy block ------------------------------------------------------------------
+
+ //parentcontroller is here be able to avoid collisions between parent/child
+
+ PHY_IPhysicsController* parentctrl = NULL;
+
+ if (destnode != destnode->GetRootSGParent())
+ {
+ KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject();
+ if (clientgameobj)
+ {
+ parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController();
+ } else
+ {
+ // it could be a false node, try the children
+ NodeList::const_iterator childit;
+ for (
+ childit = destnode->GetSGChildren().begin();
+ childit!= destnode->GetSGChildren().end();
+ ++childit
+ ) {
+ KX_GameObject* clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj)
+ {
+ parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController();
+ }
+ }
+ }
+ }
+ // end copy block ------------------------------------------------------------------
+
+ copyctrl->PostProcessReplica(motionstate, this);
+
+ return copyctrl;
+
+}
+
+void KX_OdePhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
+{
+}
+
+
+void KX_OdePhysicsController::SetSumoTransform(bool nondynaonly)
+{
+
+}
+ // todo: remove next line !
+void KX_OdePhysicsController::SetSimulatedTime(double time)
+{
+
+}
+
+#endif //USE_ODE
diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h
new file mode 100644
index 00000000000..8c3974c38a3
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h
@@ -0,0 +1,109 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __KX_ODEPHYSICSCONTROLLER_H
+#define __KX_ODEPHYSICSCONTROLLER_H
+
+#include "KX_IPhysicsController.h"
+#include "OdePhysicsController.h"
+
+/**
+ Physics Controller, a special kind of Scene Graph Transformation Controller.
+ It get's callbacks from Physics in case a transformation change took place.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changed.
+*/
+
+class KX_OdePhysicsController : public KX_IPhysicsController, public ODEPhysicsController
+
+{
+
+public:
+ KX_OdePhysicsController(
+ bool dyna,
+ bool fullRigidBody,
+ bool phantom,
+ class PHY_IMotionState* motionstate,
+ struct dxSpace* space,
+ struct dxWorld* world,
+ float mass,
+ float friction,
+ float restitution,
+ bool implicitsphere,
+ float center[3],
+ float extends[3],
+ float radius);
+
+ virtual ~KX_OdePhysicsController() {};
+
+ virtual void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse);
+ virtual void SetObject (SG_IObject* object);
+
+ virtual void RelativeTranslate(const MT_Vector3& dloc,bool local);
+ virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local);
+ virtual void ApplyTorque(const MT_Vector3& torque,bool local);
+ virtual void ApplyForce(const MT_Vector3& force,bool local);
+ virtual MT_Vector3 GetLinearVelocity();
+ virtual MT_Vector3 GetVelocity(const MT_Point3& pos);
+ virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
+ virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local);
+ virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
+ virtual void getOrientation(MT_Quaternion& orn);
+ virtual void setOrientation(const MT_Matrix3x3& orn);
+ virtual void setPosition(const MT_Point3& pos);
+ virtual void setScaling(const MT_Vector3& scaling);
+ virtual void SetTransform() {}
+ virtual MT_Scalar GetMass();
+ virtual MT_Vector3 getReactionForce();
+ virtual void setRigidBody(bool rigid);
+ virtual void AddCompoundChild(KX_IPhysicsController* child) { }
+ virtual void RemoveCompoundChild(KX_IPhysicsController* child) { }
+
+ virtual void SuspendDynamics(bool);
+ virtual void RestoreDynamics();
+ virtual MT_Scalar GetRadius();
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+ virtual float GetLinVelocityMin() { return ODEPhysicsController::GetLinVelocityMin(); }
+ virtual void SetLinVelocityMin(float val) { ODEPhysicsController::SetLinVelocityMin(val); }
+ virtual float GetLinVelocityMax() { return ODEPhysicsController::GetLinVelocityMax(); }
+ virtual void SetLinVelocityMax(float val) { ODEPhysicsController::SetLinVelocityMax(val); }
+
+ virtual void SetSumoTransform(bool nondynaonly);
+ // todo: remove next line !
+ virtual void SetSimulatedTime(double time);
+
+ // call from scene graph to update
+ virtual bool Update(double time);
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+
+};
+
+#endif //__KX_ODEPHYSICSCONTROLLER_H
+
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index befa2aaff56..cd2ed456c48 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -50,8 +50,9 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj,
int mode,
bool addToCompound,
bool ghost,
- SCA_IObject *ob)
- : SCA_IActuator(gameobj),
+ SCA_IObject *ob,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T),
m_mode(mode),
m_addToCompound(addToCompound),
m_ghost(ghost),
@@ -156,15 +157,19 @@ PyTypeObject KX_ParentActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_ParentActuator::Parents[] = {
+ &KX_ParentActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_ParentActuator::Methods[] = {
@@ -212,6 +217,18 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE
}
+PyObject* KX_ParentActuator::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_ParentActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) {
+ py_setattro_up(SCA_IActuator);
+}
+
/* Deprecated -----> */
/* 1. setObject */
const char KX_ParentActuator::SetObject_doc[] =
@@ -256,7 +273,7 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* args)
Py_RETURN_NONE;
if (ret_name_only)
- return PyUnicode_FromString(m_ob->GetName().ReadPtr());
+ return PyString_FromString(m_ob->GetName().ReadPtr());
else
return m_ob->GetProxy();
}
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h
index aeb39eabf89..148375e994c 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.h
+++ b/source/gameengine/Ketsji/KX_ParentActuator.h
@@ -68,7 +68,8 @@ class KX_ParentActuator : public SCA_IActuator
int mode,
bool addToCompound,
bool ghost,
- SCA_IObject *ob);
+ SCA_IObject *ob,
+ PyTypeObject* T=&Type);
virtual ~KX_ParentActuator();
virtual bool Update();
@@ -81,6 +82,10 @@ class KX_ParentActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
/* These are used to get and set m_ob */
static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
index 7bce311f1b6..c968e50957e 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
@@ -39,8 +39,8 @@
KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper(
PHY_IPhysicsController* ctrl,
- PHY_IPhysicsEnvironment* physenv) :
- PyObjectPlus(),
+ PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) :
+ PyObjectPlus(T),
m_ctrl(ctrl),
m_physenv(physenv)
{
@@ -129,17 +129,46 @@ PyTypeObject KX_PhysicsObjectWrapper::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
+};
+
+PyParentObject KX_PhysicsObjectWrapper::Parents[] = {
+ &KX_PhysicsObjectWrapper::Type,
+ NULL
+};
+
+PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* KX_PhysicsObjectWrapper::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+int KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj)
+{
+ int result = 1;
+
+ if (PyInt_Check(pyobj))
+ {
+ result = 0;
+ }
+ if (PyString_Check(pyobj))
+ {
+ result = 0;
+ }
+ if (result)
+ result = PyObjectPlus::py_setattro(attr,pyobj);
+
+ return result;
};
+
PyMethodDef KX_PhysicsObjectWrapper::Methods[] = {
{"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS},
{"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS},
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
index fa6fd1d1f2a..1b59686babc 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
@@ -35,8 +35,12 @@
class KX_PhysicsObjectWrapper : public PyObjectPlus
{
Py_Header;
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
public:
- KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv);
+ KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
virtual ~KX_PhysicsObjectWrapper();
KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition);
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
index a1571b17756..b56b5500c39 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.cpp
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -55,15 +55,18 @@ PyTypeObject KX_PolyProxy::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_PolyProxy::Parents[] = {
+ &KX_PolyProxy::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &PyObjectPlus::Type,
+ NULL
};
PyMethodDef KX_PolyProxy::Methods[] = {
@@ -95,17 +98,16 @@ PyAttributeDef KX_PolyProxy::Attributes[] = {
{ NULL } //Sentinel
};
-#if 0
PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
{
- char *attr_str= _PyUnicode_AsString(attr);
+ char *attr_str= PyString_AsString(attr);
if (!strcmp(attr_str, "matname"))
{
- return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
}
if (!strcmp(attr_str, "texture"))
{
- return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
}
if (!strcmp(attr_str, "material"))
{
@@ -134,35 +136,38 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
// found it
break;
}
- return PyLong_FromSsize_t(matid);
+ return PyInt_FromLong(matid);
}
if (!strcmp(attr_str, "v1"))
{
- return PyLong_FromSsize_t(m_polygon->GetVertexOffset(0));
+ return PyInt_FromLong(m_polygon->GetVertexOffset(0));
}
if (!strcmp(attr_str, "v2"))
{
- return PyLong_FromSsize_t(m_polygon->GetVertexOffset(1));
+ return PyInt_FromLong(m_polygon->GetVertexOffset(1));
}
if (!strcmp(attr_str, "v3"))
{
- return PyLong_FromSsize_t(m_polygon->GetVertexOffset(2));
+ return PyInt_FromLong(m_polygon->GetVertexOffset(2));
}
if (!strcmp(attr_str, "v4"))
{
- return PyLong_FromSsize_t(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0));
+ return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0));
}
if (!strcmp(attr_str, "visible"))
{
- return PyLong_FromSsize_t(m_polygon->IsVisible());
+ return PyInt_FromLong(m_polygon->IsVisible());
}
if (!strcmp(attr_str, "collide"))
{
- return PyLong_FromSsize_t(m_polygon->IsCollider());
+ return PyInt_FromLong(m_polygon->IsCollider());
}
- // py_getattro_up(CValue); // XXX -- todo, make all these attributes
+ py_getattro_up(CValue);
+}
+
+PyObject* KX_PolyProxy::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
}
-#endif
KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
: m_polygon(polygon),
@@ -199,37 +204,37 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex,
// found it
break;
}
- return PyLong_FromSsize_t(matid);
+ return PyInt_FromLong(matid);
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex,
"getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n")
{
- return PyLong_FromSsize_t(m_polygon->VertexCount());
+ return PyInt_FromLong(m_polygon->VertexCount());
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible,
"isVisible() : returns whether the polygon is visible or not\n")
{
- return PyLong_FromSsize_t(m_polygon->IsVisible());
+ return PyInt_FromLong(m_polygon->IsVisible());
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider,
"isCollider() : returns whether the polygon is receives collision or not\n")
{
- return PyLong_FromSsize_t(m_polygon->IsCollider());
+ return PyInt_FromLong(m_polygon->IsCollider());
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName,
"getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n")
{
- return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName,
"getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n")
{
- return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
}
KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
@@ -250,9 +255,9 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
}
if (index < m_polygon->VertexCount())
{
- return PyLong_FromSsize_t(m_polygon->GetVertexOffset(index));
+ return PyInt_FromLong(m_polygon->GetVertexOffset(index));
}
- return PyLong_FromSsize_t(0);
+ return PyInt_FromLong(0);
}
KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh,
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h
index e619617d312..d8fd36fec6c 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.h
+++ b/source/gameengine/Ketsji/KX_PolyProxy.h
@@ -52,6 +52,8 @@ public:
// stuff for python integration
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex)
KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex)
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index 9bc84127572..506c167a905 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
@@ -51,8 +51,8 @@
#include "KX_PyMath.h"
-KX_PolygonMaterial::KX_PolygonMaterial()
- : PyObjectPlus(),
+KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T)
+ : PyObjectPlus(T),
RAS_IPolyMaterial(),
m_tface(NULL),
@@ -115,7 +115,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI
PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy);
if (ret)
{
- bool value = PyLong_AsSsize_t(ret);
+ bool value = PyInt_AsLong(ret);
Py_DECREF(ret);
dopass = value;
}
@@ -255,17 +255,33 @@ PyTypeObject KX_PolygonMaterial::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject KX_PolygonMaterial::Parents[] = {
+ &KX_PolygonMaterial::Type,
+ &PyObjectPlus::Type,
+ NULL
+};
+
+PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* KX_PolygonMaterial::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(PyObjectPlus);
+}
+
KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)")
{
PyObject *material;
@@ -331,13 +347,13 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
- return PyUnicode_FromString(self->m_texturename.ReadPtr());
+ return PyString_FromString(self->m_texturename.ReadPtr());
}
PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
- return PyUnicode_FromString(self->m_materialname.ReadPtr());
+ return PyString_FromString(self->m_materialname.ReadPtr());
}
/* this does not seem useful */
@@ -354,7 +370,7 @@ PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT
if (self->m_tface && self->m_tface->tpage)
bindcode= self->m_tface->tpage->bindcode;
- return PyLong_FromSsize_t(bindcode);
+ return PyInt_FromLong(bindcode);
}
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index 266b4d7e789..89ecb026da9 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.h
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h
@@ -57,7 +57,7 @@ private:
mutable int m_pass;
public:
- KX_PolygonMaterial();
+ KX_PolygonMaterial(PyTypeObject *T = &Type);
void Initialize(const STR_String &texname,
Material* ma,
int materialindex,
@@ -116,7 +116,10 @@ public:
KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial);
KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram);
- virtual PyObject* py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); }
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
+ virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); }
static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index 94e8d1fd583..4ec901a2f5e 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -640,7 +640,7 @@ PyObject* initPythonConstraintBinding()
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
- ErrorObject = PyUnicode_FromString("PhysicsConstraints.error");
+ ErrorObject = PyString_FromString("PhysicsConstraints.error");
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index 76cfb0e572d..051d7ae7dba 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -46,6 +46,35 @@
#include "KX_Python.h"
#include "KX_PyMath.h"
+bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank)
+{
+ if (!pymat)
+ return false;
+
+ unsigned int y;
+ if (PySequence_Check(pymat))
+ {
+ unsigned int rows = PySequence_Size(pymat);
+ if (rows != rank)
+ return false;
+
+ bool ismatrix = true;
+ for (y = 0; y < rank && ismatrix; y++)
+ {
+ PyObject *pyrow = PySequence_GetItem(pymat, y); /* new ref */
+ if (PySequence_Check(pyrow))
+ {
+ if (((unsigned int)PySequence_Size(pyrow)) != rank)
+ ismatrix = false;
+ } else
+ ismatrix = false;
+ Py_DECREF(pyrow);
+ }
+ return ismatrix;
+ }
+ return false;
+}
+
bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix)
{
int size= PySequence_Size(pyval);
@@ -53,7 +82,7 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi
if (size == 4)
{
MT_Quaternion qrot;
- if (PyQuatTo(pyval, qrot))
+ if (PyVecTo(pyval, qrot))
{
rot.setRotation(qrot);
return true;
@@ -79,27 +108,14 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi
return false;
}
-bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot)
-{
- if(!PyVecTo(pyval, qrot))
- return false;
-
- /* annoying!, Blender/Mathutils have the W axis first! */
- MT_Scalar w= qrot[0]; /* from python, this is actually the W */
- qrot[0]= qrot[1];
- qrot[1]= qrot[2];
- qrot[2]= qrot[3];
- qrot[3]= w;
-
- return true;
-}
-
PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
{
-#ifdef USE_MATHUTILS
- float fmat[16];
- mat.getValue(fmat);
- return newMatrixObject(fmat, 4, 4, Py_NEW);
+#if 0
+ return Py_BuildValue("[[ffff][ffff][ffff][ffff]]",
+ mat[0][0], mat[0][1], mat[0][2], mat[0][3],
+ mat[1][0], mat[1][1], mat[1][2], mat[1][3],
+ mat[2][0], mat[2][1], mat[2][2], mat[2][3],
+ mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
#else
PyObject *list = PyList_New(4);
PyObject *sublist;
@@ -120,10 +136,11 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
{
-#ifdef USE_MATHUTILS
- float fmat[9];
- mat.getValue3x3(fmat);
- return newMatrixObject(fmat, 3, 3, Py_NEW);
+#if 0
+ return Py_BuildValue("[[fff][fff][fff]]",
+ mat[0][0], mat[0][1], mat[0][2],
+ mat[1][0], mat[1][1], mat[1][2],
+ mat[2][0], mat[2][1], mat[2][2]);
#else
PyObject *list = PyList_New(3);
PyObject *sublist;
@@ -141,20 +158,11 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
#endif
}
-#ifdef USE_MATHUTILS
-PyObject* PyObjectFrom(const MT_Quaternion &qrot)
-{
- /* NOTE, were re-ordering here for Mathutils compat */
- float fvec[4]= {qrot[3], qrot[0], qrot[1], qrot[2]};
- return newQuaternionObject(fvec, Py_WRAP);
-}
-#endif
-
PyObject* PyObjectFrom(const MT_Tuple4 &vec)
{
-#ifdef USE_MATHUTILS
- float fvec[4]= {vec[0], vec[1], vec[2], vec[3]};
- return newVectorObject(fvec, 4, Py_WRAP);
+#if 0
+ return Py_BuildValue("[ffff]",
+ vec[0], vec[1], vec[2], vec[3]);
#else
PyObject *list = PyList_New(4);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -167,9 +175,9 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec)
PyObject* PyObjectFrom(const MT_Tuple3 &vec)
{
-#ifdef USE_MATHUTILS
- float fvec[3]= {vec[0], vec[1], vec[2]};
- return newVectorObject(fvec, 3, Py_WRAP);
+#if 0
+ return Py_BuildValue("[fff]",
+ vec[0], vec[1], vec[2]);
#else
PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -181,9 +189,9 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec)
PyObject* PyObjectFrom(const MT_Tuple2 &vec)
{
-#ifdef USE_MATHUTILS
- float fvec[2]= {vec[0], vec[1]};
- return newVectorObject(fvec, 2, Py_WRAP);
+#if 0
+ return Py_BuildValue("[ff]",
+ vec[0], vec[1]);
#else
PyObject *list = PyList_New(2);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index 9ee11c9e745..a7ce4bc6930 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -42,12 +42,6 @@
#include "KX_Python.h"
#include "PyObjectPlus.h"
-#ifdef USE_MATHUTILS
-extern "C" {
-#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */
-}
-#endif
-
inline unsigned int Size(const MT_Matrix4x4&) { return 4; }
inline unsigned int Size(const MT_Matrix3x3&) { return 3; }
inline unsigned int Size(const MT_Tuple2&) { return 2; }
@@ -104,38 +98,7 @@ bool PyMatTo(PyObject* pymat, T& mat)
template<class T>
bool PyVecTo(PyObject* pyval, T& vec)
{
-#ifdef USE_MATHUTILS
- /* no need for BaseMath_ReadCallback() here, reading the sequences will do this */
-
- if(VectorObject_Check(pyval)) {
- VectorObject *pyvec= (VectorObject *)pyval;
- if (pyvec->size != Size(vec)) {
- PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", pyvec->size, Size(vec));
- return false;
- }
- vec.getValue((float *) pyvec->vec);
- return true;
- }
- else if(QuaternionObject_Check(pyval)) {
- QuaternionObject *pyquat= (QuaternionObject *)pyval;
- if (4 != Size(vec)) {
- PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 4, Size(vec));
- return false;
- }
- /* xyzw -> wxyz reordering is done by PyQuatTo */
- vec.getValue((float *) pyquat->quat);
- return true;
- }
- else if(EulerObject_Check(pyval)) {
- EulerObject *pyeul= (EulerObject *)pyval;
- if (3 != Size(vec)) {
- PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 3, Size(vec));
- return false;
- }
- vec.getValue((float *) pyeul->eul);
- return true;
- } else
-#endif
+
if(PyTuple_Check(pyval))
{
unsigned int numitems = PyTuple_GET_SIZE(pyval);
@@ -154,7 +117,7 @@ bool PyVecTo(PyObject* pyval, T& vec)
return true;
}
- else if (PyObject_TypeCheck(pyval, &PyObjectPlus::Type))
+ else if (BGE_PROXY_CHECK_TYPE(pyval))
{ /* note, include this check because PySequence_Check does too much introspection
* on the PyObject (like getting its __class__, on a BGE type this means searching up
* the parent list each time only to discover its not a sequence.
@@ -196,9 +159,6 @@ bool PyVecTo(PyObject* pyval, T& vec)
return false;
}
-
-bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot);
-
bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix);
/**
@@ -221,16 +181,15 @@ PyObject* PyObjectFrom(const MT_Tuple2 &vec);
*/
PyObject* PyObjectFrom(const MT_Tuple3 &vec);
-#ifdef USE_MATHUTILS
/**
- * Converts an MT_Quaternion to a python object.
+ * Converts an MT_Tuple4 to a python object.
*/
-PyObject* PyObjectFrom(const MT_Quaternion &qrot);
-#endif
+PyObject* PyObjectFrom(const MT_Tuple4 &pos);
/**
- * Converts an MT_Tuple4 to a python object.
+ * True if the given PyObject can be converted to an MT_Matrix
+ * @param rank = 3 (for MT_Matrix3x3) or 4 (for MT_Matrix4x4)
*/
-PyObject* PyObjectFrom(const MT_Tuple4 &pos);
+bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank);
#endif
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index eead7a51885..736460d33db 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -130,10 +130,10 @@ void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons
}
/* Macro for building the keyboard translation */
-//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromSsize_t(SCA_IInputDevice::KX_##name))
-#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name)); Py_DECREF(item)
+//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name))
+#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name)); Py_DECREF(item)
/* For the defines for types from logic bricks, we do stuff explicitly... */
-#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item)
+#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name2)); Py_DECREF(item)
// temporarily python stuff, will be put in another place later !
@@ -181,7 +181,7 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args)
BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE);
BLI_convertstringcode(expanded, gp_GamePythonPath);
- return PyUnicode_FromString(expanded);
+ return PyString_FromString(expanded);
}
static char gPySendMessage_doc[] =
@@ -306,7 +306,7 @@ static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args)
static PyObject* gPyGetMaxLogicFrame(PyObject*)
{
- return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame());
+ return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame());
}
static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args)
@@ -321,7 +321,7 @@ static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args)
static PyObject* gPyGetMaxPhysicsFrame(PyObject*)
{
- return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame());
+ return PyInt_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame());
}
static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
@@ -386,7 +386,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args)
while ((dirp = readdir(dp)) != NULL) {
if (BLI_testextensie(dirp->d_name, ".blend")) {
- value = PyUnicode_FromString(dirp->d_name);
+ value = PyString_FromString(dirp->d_name);
PyList_Append(list, value);
Py_DECREF(value);
}
@@ -500,7 +500,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
static PyObject *gEvalExpression(PyObject*, PyObject* value)
{
- char* txt= _PyUnicode_AsString(value);
+ char* txt= PyString_AsString(value);
if (txt==NULL) {
PyErr_SetString(PyExc_TypeError, "Expression.calc(text): expects a single string argument");
@@ -558,14 +558,14 @@ static struct PyMethodDef game_methods[] = {
static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args)
{
- return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0));
+ return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0));
}
static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args)
{
- return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0));
+ return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0));
}
@@ -893,7 +893,7 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*,
}
enabled = ((G.fileflags & flag) != 0);
- return PyLong_FromSsize_t(enabled);
+ return PyInt_FromLong(enabled);
}
#define KX_TEXFACE_MATERIAL 0
@@ -937,7 +937,7 @@ static PyObject* gPyGetMaterialType(PyObject*)
else
flag = KX_TEXFACE_MATERIAL;
- return PyLong_FromSsize_t(flag);
+ return PyInt_FromLong(flag);
}
static PyObject* gPyDrawLine(PyObject*, PyObject* args)
@@ -1075,7 +1075,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
PyDict_SetItemString(d, "globalDict", item=PyDict_New()); Py_DECREF(item);
- ErrorObject = PyUnicode_FromString("GameLogic.error");
+ ErrorObject = PyString_FromString("GameLogic.error");
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);
@@ -1362,7 +1362,7 @@ PyObject *KXpy_import(PyObject *self, PyObject *args)
/* check for builtin modules */
m = PyImport_AddModule("sys");
l = PyObject_GetAttrString(m, "builtin_module_names");
- n = PyUnicode_FromString(name);
+ n = PyString_FromString(name);
if (PySequence_Contains(l, n)) {
return PyImport_ImportModuleEx(name, globals, locals, fromlist);
@@ -1538,7 +1538,7 @@ static void initPySysObjects__append(PyObject *sys_path, char *filename)
BLI_split_dirfile_basic(filename, expanded, NULL); /* get the dir part of filename only */
BLI_convertstringcode(expanded, gp_GamePythonPath); /* filename from lib->filename is (always?) absolute, so this may not be needed but it wont hurt */
BLI_cleanup_file(gp_GamePythonPath, expanded); /* Dont use BLI_cleanup_dir because it adds a slash - BREAKS WIN32 ONLY */
- item= PyUnicode_FromString(expanded);
+ item= PyString_FromString(expanded);
// printf("SysPath - '%s', '%s', '%s'\n", expanded, filename, gp_GamePythonPath);
@@ -1735,7 +1735,7 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
- ErrorObject = PyUnicode_FromString("Rasterizer.error");
+ ErrorObject = PyString_FromString("Rasterizer.error");
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);
@@ -1813,10 +1813,10 @@ static PyObject* gPyEventToCharacter(PyObject*, PyObject* args)
if(IsPrintable(event)) {
char ch[2] = {'\0', '\0'};
ch[0] = ToCharacter(event, (bool)shift);
- return PyUnicode_FromString(ch);
+ return PyString_FromString(ch);
}
else {
- return PyUnicode_FromString("");
+ return PyString_FromString("");
}
}
@@ -2044,7 +2044,7 @@ int saveGamePythonConfig( char **marshal_buffer)
char *marshal_cstring;
#if PY_VERSION_HEX < 0x03000000
- marshal_cstring = _PyUnicode_AsString(pyGlobalDictMarshal);
+ marshal_cstring = PyString_AsString(pyGlobalDictMarshal);
marshal_length= PyString_Size(pyGlobalDictMarshal);
#else // py3 uses byte arrays
marshal_cstring = PyBytes_AsString(pyGlobalDictMarshal);
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index 8ff0bfd5379..83c4dcbb34c 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -87,54 +87,69 @@
#include "SCA_RandomActuator.h"
#include "SCA_IController.h"
-static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes, int init_getset)
+
+void initPyObjectPlusType(PyTypeObject **parents)
{
- PyAttributeDef *attr;
+ int i;
- if(init_getset) {
- /* we need to do this for all types before calling PyType_Ready
- * since they will call the parents PyType_Ready and those might not have initialized vars yet */
+ for (i=0; parents[i]; i++) {
+ if(PyType_Ready(parents[i]) < 0) {
+ /* This is very very unlikely */
+ printf("Error, pytype could not initialize, Blender may crash \"%s\"\n", parents[i]->tp_name);
+ return;
+ }
- //if(tp->tp_base==NULL)
- // printf("Debug: No Parents - '%s'\n" , tp->tp_name);
+#if 0
+ PyObject_Print(reinterpret_cast<PyObject *>parents[i], stderr, 0);
+ fprintf(stderr, "\n");
+ PyObject_Print(parents[i]->tp_dict, stderr, 0);
+ fprintf(stderr, "\n\n");
+#endif
- if(tp->tp_getset==NULL && attributes->m_name) {
- PyGetSetDef *attr_getset;
- int attr_tot= 0;
+ }
- for(attr= attributes; attr->m_name; attr++, attr_tot++) {};
+ PyObject *dict= NULL;
- tp->tp_getset = attr_getset = reinterpret_cast<PyGetSetDef *>(PyMem_Malloc((attr_tot+1) * sizeof(PyGetSetDef))); // XXX - Todo, free
+ while(i) {
+ i--;
+ if (dict) {
+ PyDict_Update(parents[i]->tp_dict, dict);
+ }
+ dict= parents[i]->tp_dict;
- for(attr= attributes; attr->m_name; attr++, attr_getset++) {
- attr_getset->name= (char *)attr->m_name;
- attr_getset->doc= NULL;
+#if 1
+ PyObject_Print(reinterpret_cast<PyObject *>(parents[i]), stderr, 0);
+ fprintf(stderr, "\n");
+ PyObject_Print(parents[i]->tp_dict, stderr, 0);
+ fprintf(stderr, "\n\n");
+#endif
- attr_getset->get= reinterpret_cast<getter>(PyObjectPlus::py_get_attrdef);
+ }
+}
- if(attr->m_access==KX_PYATTRIBUTE_RO)
- attr_getset->set= NULL;
- else
- attr_getset->set= reinterpret_cast<setter>(PyObjectPlus::py_set_attrdef);
- attr_getset->closure= reinterpret_cast<void *>(attr);
- }
- memset(attr_getset, 0, sizeof(PyGetSetDef));
- }
- } else {
-
- PyObject *item;
- PyType_Ready(tp);
- PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast<PyObject *>(tp));
+static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes)
+{
+ PyAttributeDef *attr;
+ PyObject *item;
+
+ PyType_Ready(tp);
+ PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast<PyObject *>(tp));
+
+ /* store attr defs in the tp_dict for to avoid string lookups */
+ for(attr= attributes; attr->m_name; attr++) {
+ item= PyCObject_FromVoidPtr(attr, NULL);
+ PyDict_SetItemString(tp->tp_dict, attr->m_name, item);
+ Py_DECREF(item);
}
}
-#define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, i)
+#define PyType_Ready_Attr(d, n) PyType_Ready_ADD(d, &n::Type, n::Attributes)
void initPyTypes(void)
{
@@ -150,82 +165,72 @@ void initPyTypes(void)
PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod);
Py_DECREF(mod);
+ PyType_Ready_Attr(dict, BL_ActionActuator);
+ PyType_Ready_Attr(dict, BL_Shader);
+ PyType_Ready_Attr(dict, BL_ShapeActionActuator);
+ PyType_Ready_Attr(dict, CListValue);
+ PyType_Ready_Attr(dict, CValue);
+ PyType_Ready_Attr(dict, KX_BlenderMaterial);
+ PyType_Ready_Attr(dict, KX_CDActuator);
+ PyType_Ready_Attr(dict, KX_Camera);
+ PyType_Ready_Attr(dict, KX_CameraActuator);
+ PyType_Ready_Attr(dict, KX_ConstraintActuator);
+ PyType_Ready_Attr(dict, KX_ConstraintWrapper);
+ PyType_Ready_Attr(dict, KX_GameActuator);
+ PyType_Ready_Attr(dict, KX_GameObject);
+ PyType_Ready_Attr(dict, KX_IpoActuator);
+ PyType_Ready_Attr(dict, KX_LightObject);
+ PyType_Ready_Attr(dict, KX_MeshProxy);
+ PyType_Ready_Attr(dict, KX_MouseFocusSensor);
+ PyType_Ready_Attr(dict, KX_NearSensor);
+ PyType_Ready_Attr(dict, KX_NetworkMessageActuator);
+ PyType_Ready_Attr(dict, KX_NetworkMessageSensor);
+ PyType_Ready_Attr(dict, KX_ObjectActuator);
+ PyType_Ready_Attr(dict, KX_ParentActuator);
+ PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper);
+ PyType_Ready_Attr(dict, KX_PolyProxy);
+ PyType_Ready_Attr(dict, KX_PolygonMaterial);
+ PyType_Ready_Attr(dict, KX_RadarSensor);
+ PyType_Ready_Attr(dict, KX_RaySensor);
+ PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator);
+ PyType_Ready_Attr(dict, KX_SCA_DynamicActuator);
+ PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator);
+ PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator);
+ PyType_Ready_Attr(dict, KX_Scene);
+ PyType_Ready_Attr(dict, KX_SceneActuator);
+ PyType_Ready_Attr(dict, KX_SoundActuator);
+ PyType_Ready_Attr(dict, KX_StateActuator);
+ PyType_Ready_Attr(dict, KX_TouchSensor);
+ PyType_Ready_Attr(dict, KX_TrackToActuator);
+ PyType_Ready_Attr(dict, KX_VehicleWrapper);
+ PyType_Ready_Attr(dict, KX_VertexProxy);
+ PyType_Ready_Attr(dict, KX_VisibilityActuator);
+ PyType_Ready_Attr(dict, PyObjectPlus);
+ PyType_Ready_Attr(dict, SCA_2DFilterActuator);
+ PyType_Ready_Attr(dict, SCA_ANDController);
+ PyType_Ready_Attr(dict, SCA_ActuatorSensor);
+ PyType_Ready_Attr(dict, SCA_AlwaysSensor);
+ PyType_Ready_Attr(dict, SCA_DelaySensor);
+ PyType_Ready_Attr(dict, SCA_ILogicBrick);
+ PyType_Ready_Attr(dict, SCA_IObject);
+ PyType_Ready_Attr(dict, SCA_ISensor);
+ PyType_Ready_Attr(dict, SCA_JoystickSensor);
+ PyType_Ready_Attr(dict, SCA_KeyboardSensor);
+ PyType_Ready_Attr(dict, SCA_MouseSensor);
+ PyType_Ready_Attr(dict, SCA_NANDController);
+ PyType_Ready_Attr(dict, SCA_NORController);
+ PyType_Ready_Attr(dict, SCA_ORController);
+ PyType_Ready_Attr(dict, SCA_PropertyActuator);
+ PyType_Ready_Attr(dict, SCA_PropertySensor);
+ PyType_Ready_Attr(dict, SCA_PythonController);
+ PyType_Ready_Attr(dict, SCA_RandomActuator);
+ PyType_Ready_Attr(dict, SCA_RandomSensor);
+ PyType_Ready_Attr(dict, SCA_XNORController);
+ PyType_Ready_Attr(dict, SCA_XORController);
+ PyType_Ready_Attr(dict, SCA_IController);
- for(int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */
- PyType_Ready_Attr(dict, BL_ActionActuator, init_getset);
- PyType_Ready_Attr(dict, BL_Shader, init_getset);
- PyType_Ready_Attr(dict, BL_ShapeActionActuator, init_getset);
- PyType_Ready_Attr(dict, CListValue, init_getset);
- PyType_Ready_Attr(dict, CValue, init_getset);
- PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset);
- PyType_Ready_Attr(dict, KX_CDActuator, init_getset);
- PyType_Ready_Attr(dict, KX_Camera, init_getset);
- PyType_Ready_Attr(dict, KX_CameraActuator, init_getset);
- PyType_Ready_Attr(dict, KX_ConstraintActuator, init_getset);
- PyType_Ready_Attr(dict, KX_ConstraintWrapper, init_getset);
- PyType_Ready_Attr(dict, KX_GameActuator, init_getset);
- PyType_Ready_Attr(dict, KX_GameObject, init_getset);
- PyType_Ready_Attr(dict, KX_IpoActuator, init_getset);
- PyType_Ready_Attr(dict, KX_LightObject, init_getset);
- PyType_Ready_Attr(dict, KX_MeshProxy, init_getset);
- PyType_Ready_Attr(dict, KX_MouseFocusSensor, init_getset);
- PyType_Ready_Attr(dict, KX_NearSensor, init_getset);
- PyType_Ready_Attr(dict, KX_NetworkMessageActuator, init_getset);
- PyType_Ready_Attr(dict, KX_NetworkMessageSensor, init_getset);
- PyType_Ready_Attr(dict, KX_ObjectActuator, init_getset);
- PyType_Ready_Attr(dict, KX_ParentActuator, init_getset);
- PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper, init_getset);
- PyType_Ready_Attr(dict, KX_PolyProxy, init_getset);
- PyType_Ready_Attr(dict, KX_PolygonMaterial, init_getset);
- PyType_Ready_Attr(dict, KX_RadarSensor, init_getset);
- PyType_Ready_Attr(dict, KX_RaySensor, init_getset);
- PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator, init_getset);
- PyType_Ready_Attr(dict, KX_SCA_DynamicActuator, init_getset);
- PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset);
- PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset);
- PyType_Ready_Attr(dict, KX_Scene, init_getset);
- PyType_Ready_Attr(dict, KX_SceneActuator, init_getset);
- PyType_Ready_Attr(dict, KX_SoundActuator, init_getset);
- PyType_Ready_Attr(dict, KX_StateActuator, init_getset);
- PyType_Ready_Attr(dict, KX_TouchSensor, init_getset);
- PyType_Ready_Attr(dict, KX_TrackToActuator, init_getset);
- PyType_Ready_Attr(dict, KX_VehicleWrapper, init_getset);
- PyType_Ready_Attr(dict, KX_VertexProxy, init_getset);
- PyType_Ready_Attr(dict, KX_VisibilityActuator, init_getset);
- PyType_Ready_Attr(dict, PyObjectPlus, init_getset);
- PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset);
- PyType_Ready_Attr(dict, SCA_ANDController, init_getset);
- PyType_Ready_Attr(dict, SCA_ActuatorSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_AlwaysSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_DelaySensor, init_getset);
- PyType_Ready_Attr(dict, SCA_ILogicBrick, init_getset);
- PyType_Ready_Attr(dict, SCA_IObject, init_getset);
- PyType_Ready_Attr(dict, SCA_ISensor, init_getset);
- PyType_Ready_Attr(dict, SCA_JoystickSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_KeyboardSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_MouseSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_NANDController, init_getset);
- PyType_Ready_Attr(dict, SCA_NORController, init_getset);
- PyType_Ready_Attr(dict, SCA_ORController, init_getset);
- PyType_Ready_Attr(dict, SCA_PropertyActuator, init_getset);
- PyType_Ready_Attr(dict, SCA_PropertySensor, init_getset);
- PyType_Ready_Attr(dict, SCA_PythonController, init_getset);
- PyType_Ready_Attr(dict, SCA_RandomActuator, init_getset);
- PyType_Ready_Attr(dict, SCA_RandomSensor, init_getset);
- PyType_Ready_Attr(dict, SCA_XNORController, init_getset);
- PyType_Ready_Attr(dict, SCA_XORController, init_getset);
- PyType_Ready_Attr(dict, SCA_IController, init_getset);
- }
-
-
/* Normal python type */
PyType_Ready(&KX_PythonSeq_Type);
-
-#ifdef USE_MATHUTILS
- /* Init mathutils callbacks */
- KX_GameObject_Mathutils_Callback_Init();
- KX_ObjectActuator_Mathutils_Callback_Init();
-#endif
}
-#endif
+#endif \ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp
index 5b4d77156db..524d957a80c 100644
--- a/source/gameengine/Ketsji/KX_PythonSeq.cpp
+++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp
@@ -221,11 +221,11 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
return NULL;
}
- if (PyLong_Check(key)) {
- return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key ));
+ if (PyInt_Check(key)) {
+ return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key ));
}
- else if ( PyUnicode_Check(key) ) {
- char *name = _PyUnicode_AsString(key);
+ else if ( PyString_Check(key) ) {
+ char *name = PyString_AsString(key);
PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name);
if(ret) {
@@ -250,12 +250,12 @@ static int KX_PythonSeq_contains(PyObject *self, PyObject *key)
PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG);
return -1;
}
- if(!PyUnicode_Check(key)) {
+ if(!PyString_Check(key)) {
PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string");
return -1;
}
- if(KX_PythonSeq_subscript__internal(self, _PyUnicode_AsString(key)))
+ if(KX_PythonSeq_subscript__internal(self, PyString_AsString(key)))
return 1;
return 0;
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index e39d3756b71..064dc9126ac 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -49,7 +49,8 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr,
double resetmargin,
bool bFindMaterial,
const STR_String& touchedpropname,
- class KX_Scene* kxscene)
+ class KX_Scene* kxscene,
+ PyTypeObject* T)
: KX_NearSensor(
eventmgr,
@@ -60,8 +61,8 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr,
bFindMaterial,
touchedpropname,
kxscene,
- physCtrl),
-
+ physCtrl,
+ T),
m_coneradius(coneradius),
m_coneheight(coneheight),
m_axis(axis)
@@ -244,15 +245,21 @@ PyTypeObject KX_RadarSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_RadarSensor::Parents[] = {
+ &KX_RadarSensor::Type,
&KX_NearSensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &KX_TouchSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_RadarSensor::Methods[] = {
@@ -276,3 +283,16 @@ PyAttributeDef KX_RadarSensor::Attributes[] = {
{NULL} //Sentinel
};
+PyObject* KX_RadarSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(KX_NearSensor);
+}
+
+PyObject* KX_RadarSensor::py_getattro_dict() {
+ py_getattro_dict_up(KX_NearSensor);
+}
+
+int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(KX_NearSensor);
+}
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h
index 344be0e399f..2e5a0e68bed 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.h
+++ b/source/gameengine/Ketsji/KX_RadarSensor.h
@@ -70,7 +70,8 @@ public:
double resetmargin,
bool bFindMaterial,
const STR_String& touchedpropname,
- class KX_Scene* kxscene);
+ class KX_Scene* kxscene,
+ PyTypeObject* T = &Type);
KX_RadarSensor();
virtual ~KX_RadarSensor();
virtual void SynchronizeTransform();
@@ -88,7 +89,9 @@ public:
KX_RADAR_AXIS_NEG_Z
};
- /* python */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
virtual sensortype GetSensorType() { return ST_RADAR; }
//Deprecated ----->
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index 3f27496df71..78a61e9d95e 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -55,8 +55,9 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
bool bXRay,
double distance,
int axis,
- KX_Scene* ketsjiScene)
- : SCA_ISensor(gameobj,eventmgr),
+ KX_Scene* ketsjiScene,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
m_propertyname(propname),
m_bFindMaterial(bFindMaterial),
m_bXRay(bXRay),
@@ -335,16 +336,20 @@ PyTypeObject KX_RaySensor::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_ISensor::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
+
+};
+PyParentObject KX_RaySensor::Parents[] = {
+ &KX_RaySensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_RaySensor::Methods[] = {
@@ -442,4 +447,18 @@ PyObject* KX_RaySensor::PyGetHitNormal()
return retVal;
}
+
+
+PyObject* KX_RaySensor::py_getattro(PyObject *attr) {
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* KX_RaySensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) {
+ py_setattro_up(SCA_ISensor);
+}
+
// <----- Deprecated
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index 530c8ce54e5..9efb046742f 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -62,7 +62,8 @@ public:
bool bXRay,
double distance,
int axis,
- class KX_Scene* ketsjiScene);
+ class KX_Scene* ketsjiScene,
+ PyTypeObject* T = &Type);
virtual ~KX_RaySensor();
virtual CValue* GetReplica();
@@ -83,6 +84,11 @@ public:
KX_RAY_AXIS_NEG_Y,
KX_RAY_AXIS_NEG_Z
};
+
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
// Deprecated ----->
KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitObject);
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index 239c4a0be67..75435b97797 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -55,9 +55,10 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
const float *linvel,
bool linv_local,
const float *angvel,
- bool angv_local)
+ bool angv_local,
+ PyTypeObject* T)
:
- SCA_IActuator(gameobj),
+ SCA_IActuator(gameobj, T),
m_OriginalObject(original),
m_scene(scene),
@@ -186,17 +187,20 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_IActuator::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject KX_SCA_AddObjectActuator::Parents[] = {
+ &KX_SCA_AddObjectActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
// ---> deprecated
{"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc},
@@ -259,6 +263,21 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con
return actuator->m_lastCreatedObject->GetProxy();
}
+
+PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SCA_AddObjectActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
/* 1. setObject */
const char KX_SCA_AddObjectActuator::SetObject_doc[] =
"setObject(object)\n"
@@ -297,7 +316,7 @@ const char KX_SCA_AddObjectActuator::SetTime_doc[] =
PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* value)
{
ShowDeprecationWarning("setTime()", "the time property");
- int deltatime = PyLong_AsSsize_t(value);
+ int deltatime = PyInt_AsLong(value);
if (deltatime==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected an int");
return NULL;
@@ -320,7 +339,7 @@ const char KX_SCA_AddObjectActuator::GetTime_doc[] =
PyObject* KX_SCA_AddObjectActuator::PyGetTime()
{
ShowDeprecationWarning("getTime()", "the time property");
- return PyLong_FromSsize_t(m_timeProp);
+ return PyInt_FromLong(m_timeProp);
}
@@ -342,7 +361,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args)
Py_RETURN_NONE;
if (ret_name_only)
- return PyUnicode_FromString(m_OriginalObject->GetName().ReadPtr());
+ return PyString_FromString(m_OriginalObject->GetName().ReadPtr());
else
return m_OriginalObject->GetProxy();
}
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
index 3151e7a89ca..6746b7d1bc6 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
@@ -88,7 +88,8 @@ public:
const float *linvel,
bool linv_local,
const float *angvel,
- bool angv_local
+ bool angv_local,
+ PyTypeObject* T=&Type
);
~KX_SCA_AddObjectActuator(void);
@@ -109,6 +110,10 @@ public:
virtual bool
Update();
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
SCA_IObject*
GetLastCreatedObject(
) const ;
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
index 423fd0db7f2..a50764a54e6 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
@@ -47,7 +47,9 @@
/* Integration hooks ------------------------------------------------------- */
-PyTypeObject KX_SCA_DynamicActuator::Type = {
+ PyTypeObject
+
+KX_SCA_DynamicActuator::Type = {
#if (PY_VERSION_HEX >= 0x02060000)
PyVarObject_HEAD_INIT(NULL, 0)
#else
@@ -64,17 +66,22 @@ PyTypeObject KX_SCA_DynamicActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_SCA_DynamicActuator::Parents[] = {
+ &KX_SCA_DynamicActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
PyMethodDef KX_SCA_DynamicActuator::Methods[] = {
// ---> deprecated
KX_PYMETHODTABLE(KX_SCA_DynamicActuator, setOperation),
@@ -89,6 +96,21 @@ PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = {
};
+PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SCA_DynamicActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
+
/* 1. setOperation */
KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation,
"setOperation(operation?)\n"
@@ -120,7 +142,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation,
)
{
ShowDeprecationWarning("getOperation()", "the mode property");
- return PyLong_FromSsize_t((long)m_dyn_operation);
+ return PyInt_FromLong((long)m_dyn_operation);
}
@@ -130,9 +152,10 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation,
KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj,
short dyn_operation,
- float setmass) :
+ float setmass,
+ PyTypeObject* T) :
- SCA_IActuator(gameobj),
+ SCA_IActuator(gameobj, T),
m_dyn_operation(dyn_operation),
m_setmass(setmass)
{
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
index 8b598c9ecfa..4add707f8cd 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
@@ -50,7 +50,8 @@ class KX_SCA_DynamicActuator : public SCA_IActuator
KX_SCA_DynamicActuator(
SCA_IObject* gameobj,
short dyn_operation,
- float setmass
+ float setmass,
+ PyTypeObject* T=&Type
);
~KX_SCA_DynamicActuator(
@@ -72,6 +73,11 @@ class KX_SCA_DynamicActuator : public SCA_IActuator
KX_DYN_SET_MASS,
};
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* 1. setOperation */
KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation);
KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,getOperation);
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
index 47c5c3aeeeb..728254e7f48 100644
--- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
@@ -43,8 +43,9 @@
#endif
KX_SCA_EndObjectActuator::KX_SCA_EndObjectActuator(SCA_IObject *gameobj,
- SCA_IScene* scene):
- SCA_IActuator(gameobj),
+ SCA_IScene* scene,
+ PyTypeObject* T):
+ SCA_IActuator(gameobj, T),
m_scene(scene)
{
// intentionally empty
@@ -107,17 +108,24 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+PyParentObject KX_SCA_EndObjectActuator::Parents[] = {
+ &KX_SCA_EndObjectActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_SCA_EndObjectActuator::Methods[] = {
{NULL,NULL} //Sentinel
};
@@ -126,4 +134,13 @@ PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SCA_EndObjectActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
/* eof */
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
index 782a24b1ef1..70d72f1f8da 100644
--- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
@@ -47,7 +47,8 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator
public:
KX_SCA_EndObjectActuator(
SCA_IObject* gameobj,
- SCA_IScene* scene
+ SCA_IScene* scene,
+ PyTypeObject* T=&Type
);
~KX_SCA_EndObjectActuator();
@@ -62,6 +63,9 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
}; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index 2884bb76565..00842d7012a 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -50,7 +50,9 @@
/* Integration hooks ------------------------------------------------------- */
-PyTypeObject KX_SCA_ReplaceMeshActuator::Type = {
+ PyTypeObject
+
+KX_SCA_ReplaceMeshActuator::Type = {
#if (PY_VERSION_HEX >= 0x02060000)
PyVarObject_HEAD_INIT(NULL, 0)
#else
@@ -67,17 +69,23 @@ PyTypeObject KX_SCA_ReplaceMeshActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = {
+ &KX_SCA_ReplaceMeshActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = {
KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh),
// Deprecated ----->
@@ -91,6 +99,20 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SCA_ReplaceMeshActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SCA_ReplaceMeshActuator* actuator = static_cast<KX_SCA_ReplaceMeshActuator*>(self);
@@ -139,7 +161,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh,
if (!m_mesh)
Py_RETURN_NONE;
- return PyUnicode_FromString(const_cast<char *>(m_mesh->GetName().ReadPtr()));
+ return PyString_FromString(const_cast<char *>(m_mesh->GetName().ReadPtr()));
}
@@ -156,9 +178,10 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh,
KX_SCA_ReplaceMeshActuator::KX_SCA_ReplaceMeshActuator(SCA_IObject *gameobj,
class RAS_MeshObject *mesh,
- SCA_IScene* scene) :
+ SCA_IScene* scene,
+ PyTypeObject* T) :
- SCA_IActuator(gameobj),
+ SCA_IActuator(gameobj, T),
m_mesh(mesh),
m_scene(scene)
{
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
index 6a68bd88cc5..0e7f7852701 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
@@ -55,7 +55,9 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
KX_SCA_ReplaceMeshActuator(
SCA_IObject* gameobj,
RAS_MeshObject *mesh,
- SCA_IScene* scene);
+ SCA_IScene* scene,
+ PyTypeObject* T=&Type
+ );
~KX_SCA_ReplaceMeshActuator(
);
@@ -69,7 +71,10 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
void InstantReplaceMesh();
- /* python api */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 51f5276e075..c0d8a7090c4 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -138,7 +138,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SND_IAudioDevice* adi,
const STR_String& sceneName,
Scene *scene):
- PyObjectPlus(),
+ PyObjectPlus(&KX_Scene::Type),
m_keyboardmgr(NULL),
m_mousemgr(NULL),
m_sceneConverter(NULL),
@@ -1629,15 +1629,17 @@ PyTypeObject KX_Scene::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_Scene::Parents[] = {
+ &KX_Scene::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ NULL
};
PyMethodDef KX_Scene::Methods[] = {
@@ -1652,7 +1654,7 @@ PyMethodDef KX_Scene::Methods[] = {
PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
- return PyUnicode_FromString(self->GetName().ReadPtr());
+ return PyString_FromString(self->GetName().ReadPtr());
}
PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1728,6 +1730,72 @@ PyAttributeDef KX_Scene::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_Scene::py_getattro__internal(PyObject *attr)
+{
+ py_getattro_up(PyObjectPlus);
+}
+
+int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(PyObjectPlus);
+}
+
+PyObject* KX_Scene::py_getattro(PyObject *attr)
+{
+ PyObject *object = py_getattro__internal(attr);
+
+ if (object==NULL)
+ {
+ PyErr_Clear();
+ object = PyDict_GetItem(m_attr_dict, attr);
+ if(object) {
+ Py_INCREF(object);
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr));
+ }
+ }
+
+ return object;
+}
+
+PyObject* KX_Scene::py_getattro_dict() {
+ //py_getattro_dict_up(PyObjectPlus);
+
+ PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict);
+ if(dict==NULL)
+ return NULL;
+
+ /* normally just return this but KX_Scene has some more items */
+
+ PyDict_Update(dict, m_attr_dict);
+ return dict;
+}
+
+int KX_Scene::py_setattro(PyObject *attr, PyObject *value)
+{
+ int ret= py_setattro__internal(attr, value);
+
+ if (ret==PY_SET_ATTR_MISSING) {
+ if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
+ PyErr_Clear();
+ ret= PY_SET_ATTR_SUCCESS;
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary");
+ ret= PY_SET_ATTR_FAIL;
+ }
+ }
+
+ return ret;
+}
+
+int KX_Scene::py_delattro(PyObject *attr)
+{
+ PyDict_DelItem(m_attr_dict, attr);
+ return 0;
+}
+
KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
"getLightList() -> list [KX_Light]\n"
"Returns a list of all lights in the scene.\n"
@@ -1752,7 +1820,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName,
)
{
ShowDeprecationWarning("getName()", "the name property");
- return PyUnicode_FromString(GetName());
+ return PyString_FromString(GetName());
}
KX_PYMETHODDEF_DOC(KX_Scene, addObject,
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 2792f1f5fe4..79d3f7fd828 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -563,7 +563,15 @@ public:
static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- virtual PyObject* py_repr(void) { return PyUnicode_FromString(GetName().ReadPtr()); }
+ virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */
+ virtual PyObject* py_getattro_dict();
+
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+ virtual int py_delattro(PyObject *attr);
+ virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); }
+
+ PyObject* py_getattro__internal(PyObject *attr);
+ int py_setattro__internal(PyObject *attr, PyObject *pyvalue);
/**
* Sets the time the scene was suspended
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp
index 5528e58ef77..1b790ec9824 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp
@@ -49,8 +49,9 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj,
KX_Scene *scene,
KX_KetsjiEngine* ketsjiEngine,
const STR_String& nextSceneName,
- KX_Camera* camera)
- : SCA_IActuator(gameobj)
+ KX_Camera* camera,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T)
{
m_mode = mode;
m_scene = scene;
@@ -133,7 +134,7 @@ bool KX_SceneActuator::Update()
{
// if no camera is set and the parent object is a camera, use it as the camera
SCA_IObject* parent = GetParent();
- if (parent->GetGameObjectType()==SCA_IObject::OBJ_CAMERA)
+ if (parent->isA(&KX_Camera::Type))
{
m_scene->SetActiveCamera((KX_Camera*)parent);
}
@@ -238,17 +239,26 @@ PyTypeObject KX_SceneActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject KX_SceneActuator::Parents[] =
+{
+ &KX_SceneActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_SceneActuator::Methods[] =
{
//Deprecated functions ------>
@@ -270,6 +280,20 @@ PyAttributeDef KX_SceneActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_SceneActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SceneActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
@@ -331,7 +355,7 @@ const char KX_SceneActuator::GetUseRestart_doc[] =
PyObject* KX_SceneActuator::PyGetUseRestart()
{
ShowDeprecationWarning("getUseRestart()", "the useRestart property");
- return PyLong_FromSsize_t(!(m_restart == 0));
+ return PyInt_FromLong(!(m_restart == 0));
}
@@ -367,7 +391,7 @@ const char KX_SceneActuator::GetScene_doc[] =
PyObject* KX_SceneActuator::PyGetScene()
{
ShowDeprecationWarning("getScene()", "the scene property");
- return PyUnicode_FromString(m_nextSceneName);
+ return PyString_FromString(m_nextSceneName);
}
@@ -408,7 +432,7 @@ PyObject* KX_SceneActuator::PyGetCamera()
{
ShowDeprecationWarning("getCamera()", "the camera property");
if (m_camera) {
- return PyUnicode_FromString(m_camera->GetName());
+ return PyString_FromString(m_camera->GetName());
}
else {
Py_RETURN_NONE;
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h
index 86de3395d1e..2412dd02590 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.h
+++ b/source/gameengine/Ketsji/KX_SceneActuator.h
@@ -77,7 +77,8 @@ class KX_SceneActuator : public SCA_IActuator
KX_Scene* scene,
KX_KetsjiEngine* ketsjiEngine,
const STR_String& nextSceneName,
- KX_Camera* camera);
+ KX_Camera* camera,
+ PyTypeObject* T=&Type);
virtual ~KX_SceneActuator();
virtual CValue* GetReplica();
@@ -91,6 +92,10 @@ class KX_SceneActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
/* 1. set */
/* Removed */
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 673f42283dd..c13271f66a5 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -50,8 +50,9 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
SND_Scene* sndscene,
KX_SOUNDACT_TYPE type,
short start,
- short end)
- : SCA_IActuator(gameobj)
+ short end,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj,T)
{
m_soundObject = sndobj;
m_soundScene = sndscene;
@@ -249,17 +250,25 @@ PyTypeObject KX_SoundActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+
+
+PyParentObject KX_SoundActuator::Parents[] = {
+ &KX_SoundActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
+
+
PyMethodDef KX_SoundActuator::Methods[] = {
// Deprecated ----->
{"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
@@ -331,13 +340,25 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
}
/* Atribute setting and getting -------------------------------------------- */
+PyObject* KX_SoundActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_SoundActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) {
+ py_setattro_up(SCA_IActuator);
+}
PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
if (!actuator->m_soundObject)
{
- return PyUnicode_FromString("");
+ return PyString_FromString("");
}
STR_String objectname = actuator->m_soundObject->GetObjectName();
char* name = objectname.Ptr();
@@ -346,7 +367,7 @@ PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYAT
PyErr_SetString(PyExc_RuntimeError, "value = actuator.fileName: KX_SoundActuator, unable to get sound fileName");
return NULL;
} else
- return PyUnicode_FromString(name);
+ return PyString_FromString(name);
}
PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
@@ -381,7 +402,7 @@ PyObject* KX_SoundActuator::pyattr_get_looping(void *self, const struct KX_PYATT
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
int looping = (actuator->m_soundObject) ? actuator->m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF;
- PyObject* result = PyLong_FromSsize_t(looping);
+ PyObject* result = PyInt_FromLong(looping);
return result;
}
@@ -559,7 +580,7 @@ PyObject* KX_SoundActuator::PyGetFilename()
ShowDeprecationWarning("getFilename()", "the fileName property");
if (!m_soundObject)
{
- return PyUnicode_FromString("");
+ return PyString_FromString("");
}
STR_String objectname = m_soundObject->GetObjectName();
char* name = objectname.Ptr();
@@ -568,7 +589,7 @@ PyObject* KX_SoundActuator::PyGetFilename()
PyErr_SetString(PyExc_RuntimeError, "Unable to get sound fileName");
return NULL;
} else
- return PyUnicode_FromString(name);
+ return PyString_FromString(name);
}
PyObject* KX_SoundActuator::PySetGain(PyObject* args)
@@ -668,7 +689,7 @@ PyObject* KX_SoundActuator::PyGetLooping()
{
ShowDeprecationWarning("getLooping()", "the looping property");
int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF;
- PyObject* result = PyLong_FromSsize_t(looping);
+ PyObject* result = PyInt_FromLong(looping);
return result;
}
@@ -756,7 +777,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* args)
PyObject* KX_SoundActuator::PyGetType()
{
ShowDeprecationWarning("getType()", "the mode property");
- return PyLong_FromSsize_t(m_type);
+ return PyInt_FromLong(m_type);
}
// <-----
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index adafee0a30b..a7491355667 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -66,7 +66,8 @@ public:
class SND_Scene* sndscene,
KX_SOUNDACT_TYPE type,
short start,
- short end);
+ short end,
+ PyTypeObject* T=&Type);
~KX_SoundActuator();
@@ -80,6 +81,10 @@ public:
/* Python interface --------------------------------------------------- */
/* -------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
+
KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound);
KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, pauseSound);
KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, stopSound);
diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp
index 9815d6274aa..f6979eee0f4 100644
--- a/source/gameengine/Ketsji/KX_StateActuator.cpp
+++ b/source/gameengine/Ketsji/KX_StateActuator.cpp
@@ -38,9 +38,10 @@
KX_StateActuator::KX_StateActuator(
SCA_IObject* gameobj,
int operation,
- unsigned int mask
+ unsigned int mask,
+ PyTypeObject* T
)
- : SCA_IActuator(gameobj),
+ : SCA_IActuator(gameobj,T),
m_operation(operation),
m_mask(mask)
{
@@ -153,18 +154,24 @@ PyTypeObject KX_StateActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject
+KX_StateActuator::Parents[] = {
+ &KX_StateActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
-PyMethodDef KX_StateActuator::Methods[] = {
+PyMethodDef
+KX_StateActuator::Methods[] = {
// deprecated -->
{"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation,
METH_VARARGS, (PY_METHODCHAR)SetOperation_doc},
@@ -180,6 +187,20 @@ PyAttributeDef KX_StateActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_StateActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_StateActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
/* set operation ---------------------------------------------------------- */
const char
diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h
index ce86c4b44fe..a4191a4c5fd 100644
--- a/source/gameengine/Ketsji/KX_StateActuator.h
+++ b/source/gameengine/Ketsji/KX_StateActuator.h
@@ -66,8 +66,9 @@ class KX_StateActuator : public SCA_IActuator
KX_StateActuator(
SCA_IObject* gameobj,
int operation,
- unsigned int mask
- );
+ unsigned int mask,
+ PyTypeObject* T=&Type
+ );
virtual
~KX_StateActuator(
@@ -88,6 +89,10 @@ class KX_StateActuator : public SCA_IActuator
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
//KX_PYMETHOD_DOC
KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation);
KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetMask);
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
new file mode 100644
index 00000000000..fc053f05e63
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
@@ -0,0 +1,244 @@
+#include "KX_ConvertPhysicsObject.h"
+
+#ifdef USE_SUMO_SOLID
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif
+
+#include "KX_SumoPhysicsController.h"
+#include "SG_Spatial.h"
+#include "SM_Scene.h"
+#include "KX_GameObject.h"
+#include "KX_MotionState.h"
+#include "KX_ClientObjectInfo.h"
+
+#include "PHY_IPhysicsEnvironment.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+void KX_SumoPhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)
+{
+ SumoPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]);
+}
+void KX_SumoPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local)
+{
+ SumoPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local);
+
+}
+void KX_SumoPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
+{
+ float oldmat[12];
+ drot.getValue(oldmat);
+/* float newmat[9];
+ float *m = &newmat[0];
+ double *orgm = &oldmat[0];
+
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; */
+
+ SumoPhysicsController::RelativeRotate(oldmat,local);
+}
+
+void KX_SumoPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local)
+{
+ SumoPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local);
+
+}
+
+void KX_SumoPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
+{
+ SumoPhysicsController::SetAngularVelocity(ang_vel[0],ang_vel[1],ang_vel[2],local);
+}
+
+MT_Vector3 KX_SumoPhysicsController::GetVelocity(const MT_Point3& pos)
+{
+
+ float linvel[3];
+ SumoPhysicsController::GetVelocity(pos[0],pos[1],pos[2],linvel[0],linvel[1],linvel[2]);
+
+ return MT_Vector3 (linvel);
+}
+
+MT_Vector3 KX_SumoPhysicsController::GetLinearVelocity()
+{
+ return GetVelocity(MT_Point3(0,0,0));
+
+}
+
+void KX_SumoPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
+{
+ SumoPhysicsController::resolveCombinedVelocities(linvelX,linvelY,linvelZ,angVelX,angVelY,angVelZ);
+}
+
+void KX_SumoPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local)
+{
+ SumoPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local);
+
+}
+
+void KX_SumoPhysicsController::ApplyForce(const MT_Vector3& force,bool local)
+{
+ SumoPhysicsController::ApplyForce(force[0],force[1],force[2],local);
+}
+
+bool KX_SumoPhysicsController::Update(double time)
+{
+ return SynchronizeMotionStates(time);
+}
+
+void KX_SumoPhysicsController::SetSimulatedTime(double time)
+{
+
+}
+
+void KX_SumoPhysicsController::SetSumoTransform(bool nondynaonly)
+{
+ SumoPhysicsController::setSumoTransform(nondynaonly);
+
+}
+
+void KX_SumoPhysicsController::SuspendDynamics(bool)
+{
+ SumoPhysicsController::SuspendDynamics();
+}
+
+void KX_SumoPhysicsController::RestoreDynamics()
+{
+ SumoPhysicsController::RestoreDynamics();
+}
+
+SG_Controller* KX_SumoPhysicsController::GetReplica(SG_Node* destnode)
+{
+
+ PHY_IMotionState* motionstate = new KX_MotionState(destnode);
+
+ KX_SumoPhysicsController* physicsreplica = new KX_SumoPhysicsController(*this);
+
+ //parentcontroller is here be able to avoid collisions between parent/child
+
+ PHY_IPhysicsController* parentctrl = NULL;
+
+ if (destnode != destnode->GetRootSGParent())
+ {
+ KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject();
+ if (clientgameobj)
+ {
+ parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController();
+ } else
+ {
+ // it could be a false node, try the children
+ NodeList::const_iterator childit;
+ for (
+ childit = destnode->GetSGChildren().begin();
+ childit!= destnode->GetSGChildren().end();
+ ++childit
+ ) {
+ KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj)
+ {
+ parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController();
+ }
+ }
+ }
+ }
+
+ physicsreplica->PostProcessReplica(motionstate,parentctrl);
+
+ return physicsreplica;
+}
+
+
+void KX_SumoPhysicsController::SetObject (SG_IObject* object)
+{
+ SG_Controller::SetObject(object);
+
+ // cheating here...
+//should not be necessary, is it for duplicates ?
+
+KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject();
+gameobj->SetPhysicsController(this,gameobj->IsDynamic());
+GetSumoObject()->setClientObject(gameobj->getClientInfo());
+}
+
+void KX_SumoPhysicsController::setMargin(float collisionMargin)
+{
+ SumoPhysicsController::SetMargin(collisionMargin);
+}
+
+
+void KX_SumoPhysicsController::setOrientation(const MT_Matrix3x3& rot)
+{
+ MT_Quaternion orn = rot.getRotation();
+ SumoPhysicsController::setOrientation(
+ orn[0],orn[1],orn[2],orn[3]);
+
+}
+void KX_SumoPhysicsController::getOrientation(MT_Quaternion& orn)
+{
+
+ float quat[4];
+
+ SumoPhysicsController::getOrientation(quat[0],quat[1],quat[2],quat[3]);
+
+ orn = MT_Quaternion(quat);
+
+}
+
+void KX_SumoPhysicsController::setPosition(const MT_Point3& pos)
+{
+ SumoPhysicsController::setPosition(pos[0],pos[1],pos[2]);
+
+}
+
+void KX_SumoPhysicsController::setScaling(const MT_Vector3& scaling)
+{
+ SumoPhysicsController::setScaling(scaling[0],scaling[1],scaling[2]);
+
+}
+
+MT_Scalar KX_SumoPhysicsController::GetMass()
+{
+ return SumoPhysicsController::getMass();
+}
+
+void KX_SumoPhysicsController::SetMass(MT_Scalar newmass)
+{
+}
+
+MT_Vector3 KX_SumoPhysicsController::GetLocalInertia()
+{
+ return MT_Vector3(0.f, 0.f, 0.f); // \todo
+}
+
+MT_Scalar KX_SumoPhysicsController::GetRadius()
+{
+ return SumoPhysicsController::GetRadius();
+}
+
+MT_Vector3 KX_SumoPhysicsController::getReactionForce()
+{
+ float force[3];
+ SumoPhysicsController::getReactionForce(force[0],force[1],force[2]);
+ return MT_Vector3(force);
+
+}
+
+void KX_SumoPhysicsController::setRigidBody(bool rigid)
+{
+ SumoPhysicsController::setRigidBody(rigid);
+
+}
+
+
+KX_SumoPhysicsController::~KX_SumoPhysicsController()
+{
+
+
+}
+
+
+#endif//USE_SUMO_SOLID
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
new file mode 100644
index 00000000000..278994c6ae7
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
@@ -0,0 +1,122 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __KX_SUMOPHYSICSCONTROLLER_H
+#define __KX_SUMOPHYSICSCONTROLLER_H
+
+#include "PHY_IPhysicsController.h"
+
+/**
+ Physics Controller, a special kind of Scene Graph Transformation Controller.
+ It get's callbacks from Sumo in case a transformation change took place.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changed.
+*/
+
+#include "SumoPhysicsController.h"
+#include "KX_IPhysicsController.h"
+
+class KX_SumoPhysicsController : public KX_IPhysicsController,
+ public SumoPhysicsController
+
+{
+
+
+public:
+ KX_SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate
+ ,bool dyna)
+ : KX_IPhysicsController(dyna,false,false,NULL) ,
+ SumoPhysicsController(sumoScene,/*solidscene,*/sumoObj,motionstate,dyna)
+ {
+ };
+ virtual ~KX_SumoPhysicsController();
+
+ void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse);
+ virtual void SetObject (SG_IObject* object);
+ virtual void setMargin (float collisionMargin);
+
+ void RelativeTranslate(const MT_Vector3& dloc,bool local);
+ void RelativeRotate(const MT_Matrix3x3& drot,bool local);
+ void ApplyTorque(const MT_Vector3& torque,bool local);
+ void ApplyForce(const MT_Vector3& force,bool local);
+ MT_Vector3 GetLinearVelocity();
+ MT_Vector3 GetAngularVelocity() // to keep compiler happy
+ { return MT_Vector3(0.0,0.0,0.0); }
+ MT_Vector3 GetVelocity(const MT_Point3& pos);
+ void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
+ void SetLinearVelocity(const MT_Vector3& lin_vel,bool local);
+ void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
+
+
+ void SuspendDynamics(bool);
+ void RestoreDynamics();
+ virtual void AddCompoundChild(KX_IPhysicsController* child) { }
+ virtual void RemoveCompoundChild(KX_IPhysicsController* child) { }
+
+ virtual void getOrientation(MT_Quaternion& orn);
+ virtual void setOrientation(const MT_Matrix3x3& orn);
+ virtual void SetTransform() {}
+
+ virtual void setPosition(const MT_Point3& pos);
+ virtual void setScaling(const MT_Vector3& scaling);
+ virtual MT_Scalar GetMass();
+ virtual void SetMass(MT_Scalar newmass);
+ virtual MT_Vector3 GetLocalInertia();
+ virtual MT_Scalar GetRadius();
+ virtual MT_Vector3 getReactionForce();
+ virtual void setRigidBody(bool rigid);
+
+ virtual float GetLinVelocityMin() { return SumoPhysicsController::GetLinVelocityMin(); }
+ virtual void SetLinVelocityMin(float val) { SumoPhysicsController::SetLinVelocityMin(val); }
+ virtual float GetLinVelocityMax() { return SumoPhysicsController::GetLinVelocityMax(); }
+ virtual void SetLinVelocityMax(float val) { SumoPhysicsController::SetLinVelocityMax(val); }
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+
+ void SetSumoTransform(bool nondynaonly);
+ // todo: remove next line !
+ virtual void SetSimulatedTime(double time);
+
+ // call from scene graph to update
+ virtual bool Update(double time);
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+};
+
+#endif //__KX_SUMOPHYSICSCONTROLLER_H
+
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index b0cf172c27a..c06acd4a873 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -97,8 +97,8 @@ bool KX_TouchSensor::Evaluate()
return result;
}
-KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname)
-:SCA_ISensor(gameobj,eventmgr),
+KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname,PyTypeObject* T)
+:SCA_ISensor(gameobj,eventmgr,T),
m_touchedpropname(touchedpropname),
m_bFindMaterial(bFindMaterial),
m_bTouchPulse(bTouchPulse),
@@ -310,15 +310,19 @@ PyTypeObject KX_TouchSensor::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_TouchSensor::Parents[] = {
+ &KX_TouchSensor::Type,
&SCA_ISensor::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
PyMethodDef KX_TouchSensor::Methods[] = {
@@ -344,6 +348,20 @@ PyAttributeDef KX_TouchSensor::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_TouchSensor::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_ISensor);
+}
+
+PyObject* KX_TouchSensor::py_getattro_dict() {
+ py_getattro_dict_up(SCA_ISensor);
+}
+
+int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_ISensor);
+}
+
/* Python API */
/* 1. setProperty */
@@ -356,7 +374,7 @@ const char KX_TouchSensor::SetProperty_doc[] =
PyObject* KX_TouchSensor::PySetProperty(PyObject* value)
{
ShowDeprecationWarning("setProperty()", "the propName property");
- char *nameArg= _PyUnicode_AsString(value);
+ char *nameArg= PyString_AsString(value);
if (nameArg==NULL) {
PyErr_SetString(PyExc_ValueError, "expected a ");
return NULL;
@@ -374,7 +392,7 @@ const char KX_TouchSensor::GetProperty_doc[] =
PyObject* KX_TouchSensor::PyGetProperty() {
ShowDeprecationWarning("getProperty()", "the propName property");
- return PyUnicode_FromString(m_touchedpropname);
+ return PyString_FromString(m_touchedpropname);
}
const char KX_TouchSensor::GetHitObject_doc[] =
@@ -415,7 +433,7 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] =
PyObject* KX_TouchSensor::PyGetTouchMaterial()
{
ShowDeprecationWarning("getTouchMaterial()", "the useMaterial property");
- return PyLong_FromSsize_t(m_bFindMaterial);
+ return PyInt_FromLong(m_bFindMaterial);
}
/* 6. setTouchMaterial */
@@ -428,7 +446,7 @@ const char KX_TouchSensor::SetTouchMaterial_doc[] =
PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject *value)
{
ShowDeprecationWarning("setTouchMaterial()", "the useMaterial property");
- int pulseArg = PyLong_AsSsize_t(value);
+ int pulseArg = PyInt_AsLong(value);
if(pulseArg ==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "expected a bool");
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index 6cbf5b15e3b..476c63e89db 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -79,7 +79,8 @@ public:
class KX_GameObject* gameobj,
bool bFindMaterial,
bool bTouchPulse,
- const STR_String& touchedpropname) ;
+ const STR_String& touchedpropname,
+ PyTypeObject* T=&Type) ;
virtual ~KX_TouchSensor();
virtual CValue* GetReplica();
@@ -120,6 +121,10 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
//Deprecated ----->
/* 1. setProperty */
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index e8a06d8d619..5a50d0fb944 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -59,8 +59,10 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj,
int time,
bool allow3D,
int trackflag,
- int upflag)
- : SCA_IActuator(gameobj)
+ int upflag,
+ PyTypeObject* T)
+ :
+ SCA_IActuator(gameobj, T)
{
m_time = time;
m_allow3D = allow3D;
@@ -72,6 +74,7 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj,
if (m_object)
m_object->RegisterActuator(this);
+ if (gameobj->isA(&KX_GameObject::Type))
{
// if the object is vertex parented, don't check parent orientation as the link is broken
if (!((KX_GameObject*)gameobj)->IsVertexParent()){
@@ -447,17 +450,25 @@ PyTypeObject KX_TrackToActuator::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &SCA_IActuator::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+
+
+PyParentObject KX_TrackToActuator::Parents[] = {
+ &KX_TrackToActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
PyMethodDef KX_TrackToActuator::Methods[] = {
// ---> deprecated
{"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc},
@@ -507,6 +518,20 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT
}
+PyObject* KX_TrackToActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_TrackToActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
/* 1. setObject */
const char KX_TrackToActuator::SetObject_doc[] =
"setObject(object)\n"
@@ -551,7 +576,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* args)
Py_RETURN_NONE;
if (ret_name_only)
- return PyUnicode_FromString(m_object->GetName());
+ return PyString_FromString(m_object->GetName());
else
return m_object->GetProxy();
}
@@ -588,7 +613,7 @@ const char KX_TrackToActuator::GetTime_doc[] =
PyObject* KX_TrackToActuator::PyGetTime()
{
ShowDeprecationWarning("getTime()", "the timer property");
- return PyLong_FromSsize_t(m_time);
+ return PyInt_FromLong(m_time);
}
@@ -600,7 +625,7 @@ const char KX_TrackToActuator::GetUse3D_doc[] =
PyObject* KX_TrackToActuator::PyGetUse3D()
{
ShowDeprecationWarning("setTime()", "the use3D property");
- return PyLong_FromSsize_t(!(m_allow3D == 0));
+ return PyInt_FromLong(!(m_allow3D == 0));
}
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h
index 801e695bb9b..c4cc2b1f062 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.h
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.h
@@ -56,7 +56,7 @@ class KX_TrackToActuator : public SCA_IActuator
public:
KX_TrackToActuator(SCA_IObject* gameobj, SCA_IObject *ob, int time,
- bool threedee,int trackflag,int upflag);
+ bool threedee,int trackflag,int upflag, PyTypeObject* T=&Type);
virtual ~KX_TrackToActuator();
virtual CValue* GetReplica() {
KX_TrackToActuator* replica = new KX_TrackToActuator(*this);
@@ -70,6 +70,9 @@ class KX_TrackToActuator : public SCA_IActuator
virtual bool Update(double curtime, bool frame);
/* Python part */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject* value);
/* These are used to get and set m_ob */
static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 7001bfc8b7e..8146d04a878 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -16,8 +16,8 @@
KX_VehicleWrapper::KX_VehicleWrapper(
PHY_IVehicle* vehicle,
- PHY_IPhysicsEnvironment* physenv) :
- PyObjectPlus(),
+ PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) :
+ PyObjectPlus(T),
m_vehicle(vehicle),
m_physenv(physenv)
{
@@ -127,13 +127,13 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args)
PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args)
{
- return PyLong_FromSsize_t(m_vehicle->GetNumWheels());
+ return PyInt_FromLong(m_vehicle->GetNumWheels());
}
PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args)
{
- return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId());
+ return PyInt_FromLong(m_vehicle->GetUserConstraintId());
}
@@ -264,7 +264,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args)
PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args)
{
- return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType());
+ return PyInt_FromLong(m_vehicle->GetUserConstraintType());
}
@@ -289,17 +289,35 @@ PyTypeObject KX_VehicleWrapper::Type = {
0,
0,
py_base_repr,
- 0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
- &PyObjectPlus::Type,
0,0,0,0,0,0,
- py_base_new
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
+PyParentObject KX_VehicleWrapper::Parents[] = {
+ &KX_VehicleWrapper::Type,
+ &PyObjectPlus::Type,
+ NULL
+};
+
+PyObject* KX_VehicleWrapper::py_getattro(PyObject *attr)
+{
+ //here you can search for existing data members (like mass,friction etc.)
+ py_getattro_up(PyObjectPlus);
+}
+
+PyObject* KX_VehicleWrapper::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* value)
+{
+ py_setattro_up(PyObjectPlus);
+};
+
+
PyMethodDef KX_VehicleWrapper::Methods[] = {
{"addWheel",(PyCFunction) KX_VehicleWrapper::sPyAddWheel, METH_VARARGS},
{"getNumWheels",(PyCFunction) KX_VehicleWrapper::sPyGetNumWheels, METH_VARARGS},
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h
index d7f2da5cd7c..c2b5e3d9251 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.h
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h
@@ -12,11 +12,14 @@ class PHY_IMotionState;
class KX_VehicleWrapper : public PyObjectPlus
{
Py_Header;
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
std::vector<PHY_IMotionState*> m_motionStates;
public:
- KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv);
+ KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
virtual ~KX_VehicleWrapper ();
int getConstraintId();
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index cb8c891969d..4b0ad083473 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -53,15 +53,18 @@ PyTypeObject KX_VertexProxy::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+};
+
+PyParentObject KX_VertexProxy::Parents[] = {
+ &KX_VertexProxy::Type,
&CValue::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &PyObjectPlus::Type,
+ NULL
};
PyMethodDef KX_VertexProxy::Methods[] = {
@@ -82,38 +85,37 @@ PyMethodDef KX_VertexProxy::Methods[] = {
PyAttributeDef KX_VertexProxy::Attributes[] = {
//KX_PYATTRIBUTE_TODO("DummyProps"),
-
+
KX_PYATTRIBUTE_DUMMY("x"),
KX_PYATTRIBUTE_DUMMY("y"),
KX_PYATTRIBUTE_DUMMY("z"),
-
+
KX_PYATTRIBUTE_DUMMY("r"),
KX_PYATTRIBUTE_DUMMY("g"),
KX_PYATTRIBUTE_DUMMY("b"),
KX_PYATTRIBUTE_DUMMY("a"),
-
+
KX_PYATTRIBUTE_DUMMY("u"),
KX_PYATTRIBUTE_DUMMY("v"),
-
+
KX_PYATTRIBUTE_DUMMY("u2"),
KX_PYATTRIBUTE_DUMMY("v2"),
-
+
KX_PYATTRIBUTE_DUMMY("XYZ"),
KX_PYATTRIBUTE_DUMMY("UV"),
-
+
KX_PYATTRIBUTE_DUMMY("color"),
KX_PYATTRIBUTE_DUMMY("colour"),
-
+
KX_PYATTRIBUTE_DUMMY("normal"),
-
+
{ NULL } //Sentinel
};
-#if 0
PyObject*
KX_VertexProxy::py_getattro(PyObject *attr)
{
- char *attr_str= _PyUnicode_AsString(attr);
+ char *attr_str= PyString_AsString(attr);
if (attr_str[1]=='\0') { // Group single letters
// pos
if (attr_str[0]=='x')
@@ -139,8 +141,8 @@ KX_VertexProxy::py_getattro(PyObject *attr)
if (attr_str[0]=='v')
return PyFloat_FromDouble(m_vertex->getUV1()[1]);
}
-
-
+
+
if (!strcmp(attr_str, "XYZ"))
return PyObjectFrom(MT_Vector3(m_vertex->getXYZ()));
@@ -154,21 +156,22 @@ KX_VertexProxy::py_getattro(PyObject *attr)
color /= 255.0;
return PyObjectFrom(color);
}
-
+
if (!strcmp(attr_str, "normal"))
{
return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
}
-
+
py_getattro_up(CValue);
}
-#endif
+PyObject* KX_VertexProxy::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
-#if 0
int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
{
- char *attr_str= _PyUnicode_AsString(attr);
+ char *attr_str= PyString_AsString(attr);
if (PySequence_Check(pyvalue))
{
if (!strcmp(attr_str, "XYZ"))
@@ -182,7 +185,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
}
return PY_SET_ATTR_FAIL;
}
-
+
if (!strcmp(attr_str, "UV"))
{
MT_Point2 vec;
@@ -194,7 +197,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
}
return PY_SET_ATTR_FAIL;
}
-
+
if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour"))
{
MT_Vector4 vec;
@@ -206,7 +209,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
}
return PY_SET_ATTR_FAIL;
}
-
+
if (!strcmp(attr_str, "normal"))
{
MT_Vector3 vec;
@@ -219,7 +222,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
return PY_SET_ATTR_FAIL;
}
}
-
+
if (PyFloat_Check(pyvalue))
{
float val = PyFloat_AsDouble(pyvalue);
@@ -232,7 +235,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
-
+
if (!strcmp(attr_str, "y"))
{
pos.y() = val;
@@ -240,7 +243,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
-
+
if (!strcmp(attr_str, "z"))
{
pos.z() = val;
@@ -248,7 +251,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
-
+
// uv
MT_Point2 uv = m_vertex->getUV1();
if (!strcmp(attr_str, "u"))
@@ -284,7 +287,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
-
+
// col
unsigned int icol = *((const unsigned int *)m_vertex->getRGBA());
unsigned char *cp = (unsigned char*) &icol;
@@ -318,10 +321,9 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
return PY_SET_ATTR_SUCCESS;
}
}
-
+
return CValue::py_setattro(attr, pyvalue);
}
-#endif
KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex)
: m_vertex(vertex),
@@ -337,7 +339,7 @@ KX_VertexProxy::~KX_VertexProxy()
// stuff for cvalue related things
CValue* KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
-CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}
+CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}
STR_String sVertexName="vertex";
const STR_String & KX_VertexProxy::GetText() {return sVertexName;};
double KX_VertexProxy::GetNumber() { return -1;}
@@ -346,7 +348,7 @@ void KX_VertexProxy::SetName(const char *) { };
CValue* KX_VertexProxy::GetReplica() { return NULL;}
// stuff for python integration
-
+
PyObject* KX_VertexProxy::PyGetXYZ()
{
return PyObjectFrom(MT_Point3(m_vertex->getXYZ()));
@@ -357,7 +359,7 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject* value)
MT_Point3 vec;
if (!PyVecTo(value, vec))
return NULL;
-
+
m_vertex->SetXYZ(vec);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
@@ -373,7 +375,7 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value)
MT_Vector3 vec;
if (!PyVecTo(value, vec))
return NULL;
-
+
m_vertex->SetNormal(vec);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
@@ -383,18 +385,18 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value)
PyObject* KX_VertexProxy::PyGetRGBA()
{
int *rgba = (int *) m_vertex->getRGBA();
- return PyLong_FromSsize_t(*rgba);
+ return PyInt_FromLong(*rgba);
}
PyObject* KX_VertexProxy::PySetRGBA(PyObject* value)
{
- if PyLong_Check(value) {
- int rgba = PyLong_AsSsize_t(value);
+ if PyInt_Check(value) {
+ int rgba = PyInt_AsLong(value);
m_vertex->SetRGBA(rgba);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
}
- else {
+ else {
MT_Vector4 vec;
if (PyVecTo(value, vec))
{
@@ -403,7 +405,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value)
Py_RETURN_NONE;
}
}
-
+
PyErr_SetString(PyExc_TypeError, "vert.setRGBA(value): KX_VertexProxy, expected a 4D vector or an int");
return NULL;
}
@@ -419,7 +421,7 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value)
MT_Point2 vec;
if (!PyVecTo(value, vec))
return NULL;
-
+
m_vertex->SetUV(vec);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
@@ -434,14 +436,14 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject* args)
{
MT_Point2 vec;
unsigned int unit= RAS_TexVert::SECOND_UV;
-
+
PyObject* list= NULL;
if(!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit))
return NULL;
-
+
if (!PyVecTo(list, vec))
return NULL;
-
+
m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV));
m_vertex->SetUnit(unit);
m_vertex->SetUV2(vec);
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h
index 13c57e9f556..42db5fbc322 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.h
+++ b/source/gameengine/Ketsji/KX_VertexProxy.h
@@ -53,6 +53,9 @@ public:
// stuff for python integration
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ);
KX_PYMETHOD_O(KX_VertexProxy,SetXYZ);
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
index 3561ccde9d9..d848065ad73 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
@@ -39,9 +39,10 @@ KX_VisibilityActuator::KX_VisibilityActuator(
SCA_IObject* gameobj,
bool visible,
bool occlusion,
- bool recursive
+ bool recursive,
+ PyTypeObject* T
)
- : SCA_IActuator(gameobj),
+ : SCA_IActuator(gameobj,T),
m_visible(visible),
m_occlusion(occlusion),
m_recursive(recursive)
@@ -107,18 +108,25 @@ PyTypeObject KX_VisibilityActuator::Type = {
0,
0,
py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
0,0,0,0,0,0,0,0,0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- 0,0,0,0,0,0,0,
- Methods,
- 0,
- 0,
+ Methods
+
+};
+
+PyParentObject
+KX_VisibilityActuator::Parents[] = {
+ &KX_VisibilityActuator::Type,
&SCA_IActuator::Type,
- 0,0,0,0,0,0,
- py_base_new
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
};
-PyMethodDef KX_VisibilityActuator::Methods[] = {
+PyMethodDef
+KX_VisibilityActuator::Methods[] = {
// Deprecated ----->
{"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible, METH_VARARGS,
(PY_METHODCHAR) SetVisible_doc},
@@ -133,6 +141,21 @@ PyAttributeDef KX_VisibilityActuator::Attributes[] = {
{ NULL } //Sentinel
};
+PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr)
+{
+ py_getattro_up(SCA_IActuator);
+}
+
+PyObject* KX_VisibilityActuator::py_getattro_dict() {
+ py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value)
+{
+ py_setattro_up(SCA_IActuator);
+}
+
+
/* set visibility ---------------------------------------------------------- */
const char
KX_VisibilityActuator::SetVisible_doc[] =
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h
index 3ad50c6cea2..45aba50f645 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.h
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h
@@ -48,7 +48,9 @@ class KX_VisibilityActuator : public SCA_IActuator
SCA_IObject* gameobj,
bool visible,
bool occlusion,
- bool recursive);
+ bool recursive,
+ PyTypeObject* T=&Type
+ );
virtual
~KX_VisibilityActuator(
@@ -67,6 +69,10 @@ class KX_VisibilityActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+
// Deprecated ----->
KX_PYMETHOD_DOC_VARARGS(KX_VisibilityActuator,SetVisible);
// <-----
diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile
index 8e91eb6ff9a..59b3ff178fb 100644
--- a/source/gameengine/Ketsji/Makefile
+++ b/source/gameengine/Ketsji/Makefile
@@ -44,7 +44,7 @@ CPPFLAGS += -I../../blender/python
CPPFLAGS += -I../../blender/python/generic
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
-CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include
CPPFLAGS += -I$(NAN_SOLID)/include
CPPFLAGS += -I$(NAN_BULLET2)/include
CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
@@ -54,11 +54,14 @@ CPPFLAGS += -I../../kernel/gen_system
CPPFLAGS += -I../Network -IKXNetwork
CPPFLAGS += -I../Physics/common
CPPFLAGS += -I../Physics/Dummy
+CPPFLAGS += -I../Physics/Sumo
+CPPFLAGS += -I../Physics/BlOde
CPPFLAGS += -I../Physics/Bullet
CPPFLAGS += -I.
CPPFLAGS += -I../Converter
CPPFLAGS += -I../../blender/blenkernel
CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/editors/include
CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I../../blender/imbuf
CPPFLAGS += -I../../blender/gpu
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index b09267b79ff..49dbacc8916 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -18,9 +18,16 @@ incs += ' #source/blender/blenkernel #source/blender #source/blender/editors/inc
incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Rasterizer'
incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network'
incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #source/gameengine/Physics/Bullet'
-incs += ' #source/gameengine/Physics/Dummy'
+incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy'
incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu'
+if env['WITH_BF_SOLID']:
+ incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include'
+ incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork'
+ incs += ' ' + env['BF_SOLID_INC']
+ defs += ' USE_SUMO_SOLID'
+
+
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_BULLET_INC']
incs += ' ' + env['BF_OPENGL_INC']
diff --git a/source/gameengine/Physics/BlOde/Makefile b/source/gameengine/Physics/BlOde/Makefile
new file mode 100644
index 00000000000..1fbbf198377
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/Makefile
@@ -0,0 +1,48 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = blode
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_ODE)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
+# nlin: fix this, should put in NAN_ODE dir
+#CPPFLAGS += -I./ode/ode/include
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.cpp b/source/gameengine/Physics/BlOde/OdePhysicsController.cpp
new file mode 100644
index 00000000000..5efd0994311
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/OdePhysicsController.cpp
@@ -0,0 +1,625 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#define USE_ODE
+#ifdef USE_ODE
+
+#include "OdePhysicsController.h"
+#include "PHY_IMotionState.h"
+
+#include <ode/ode.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+//
+// general to-do list for ODE physics. This is maintained in doxygen format.
+//
+/// \todo determine assignment time for bounding spheres.
+///
+/// it appears you have to select "sphere" for bounding volume AND "draw bounds"
+/// in order for a bounding sphere to be generated. otherwise a box is generated.
+/// determine exactly when and how the bounding volumes are generated and make
+/// this consistent.
+/// }
+///
+/// \todo bounding sphere size incorrect
+///
+/// it appears NOT to use the size of the shown bounding sphere (button "draw bounds").
+/// it appears instead to use the size of the "size" dynamic parameter in the
+/// gamebuttons but this "size" draws an incorrectly-sized circle on screen for the
+/// bounding sphere (leftover skewed size calculation from sumo?) so figure out WHERE
+/// its getting the radius from.
+///
+/// \todo ODE collisions must fire collision actuator
+///
+/// See OdePhysicsEnvironment::OdeNearCallback. If a sensor was created to check
+/// for the presence of this collision, then in the NearCallback you need to
+/// take appropriate action regarding the sensor - something like checking its
+/// controller and if needed firing its actuator. Need to find similar code in
+/// Fuzzics which fires collision controllers/actuators.
+///
+/// \todo Are ghost collisions possible?
+///
+/// How do ghost collisions work? Do they require collision detection through ODE
+/// and NON-CREATION of contact-joint in OdeNearCallback? Currently OdeNearCallback
+/// creates joints ALWAYS for collisions.
+///
+/// \todo Why is KX_GameObject::addLinearVelocity commented out?
+///
+/// Try putting this code back in.
+///
+/// \todo Too many non-dynamic actors bogs down ODE physics
+///
+/// Lots of "geoms" (ODE static geometry) probably slows down ode. Try a test file
+/// with lots of static geometry - the game performance in Blender says it is
+/// spending all its time in physics, and I bet all that time is in collision
+/// detection. It's ode's non-hierarchical collision detection.
+/// try making a separate ode test program (not within blender) with 1000 geoms and
+/// see how fast it is. if it is really slow, there is the culprit.
+/// isnt someone working on an improved ODE collision detector? check
+/// ode mailing list.
+///
+///
+/// \todo support collision of dynas with non-dynamic triangle meshes
+///
+/// ODE has trimesh-collision support but only for trimeshes without a transform
+/// matrix. update ODE tricollider to support a transform matrix. this will allow
+/// moving trimeshes non-dynamically (e.g. through Ipos). then collide trimeshes
+/// with dynas. this allows dynamic primitives (spheres, boxes) to collide with
+/// non-dynamic or kinematically controlled tri-meshes. full dynamic trimesh to
+/// dynamic trimesh support is hard because it requires (a) collision and penetration
+/// depth for trimesh to trimesh and (hard to compute) (b) an intertia tensor
+/// (easy to compute).
+///
+/// a triangle mesh collision geometry should be created when the blender
+/// bounding volume (F9, EDITBUTTONS) is set to "polyheder", since this is
+/// currently the place where sphere/box selection is made
+///
+/// \todo specify ODE ERP+CFM in blender interface
+///
+/// when ODE physics selected, have to be able to set global cfm and erp.
+/// per-joint erp/cfm could be handled in constraint window.
+///
+/// \todo moving infinite mass objects should impart extra impulse to objects they collide with
+///
+/// currently ODE's ERP pushes them apart but doesn't account for their motion.
+/// you have to detect if one body in a collision is a non-dyna. This
+/// requires adding a new accessor method to
+/// KX_IPhysicsInterfaceController to access the hidden m_isDyna variable,
+/// currently it can only be written, not read). If one of the bodies in a
+/// collision is a non-dyna, then impart an extra impulse based on the
+/// motion of the static object (using its last 2 frames as an approximation
+/// of its linear and angular velocity). Linear velocity is easy to
+/// approximate, but angular? you have orientation at this frame and
+/// orientation at previous frame. The question is what is the angular
+/// velocity which would have taken you from the previous frame's orientation
+/// to this frame's orientation?
+///
+/// \todo allow tweaking bounding volume size
+///
+/// the scene converter currently uses the blender bounding volume of the selected
+/// object as the geometry for ODE collision purposes. this is good and automatic
+/// intuitive - lets you choose between cube, sphere, mesh. but you need to be able
+/// to tweak this size for physics.
+///
+/// \todo off center meshes totally wrong for ode
+///
+/// ode uses x, y, z extents regradless of center. then places geom at center of object.
+/// but visual geom is not necessarily at center. need to detect off-center situations.
+/// then do what? treat it as an encapsulated off-center mass, or recenter it?
+///
+/// i.o.w. recalculate center, or recalculate mass distribution (using encapsulation)?
+///
+/// \todo allow off-center mass
+///
+/// using ode geometry encapsulators
+///
+/// \todo allow entering compound geoms for complex collision shapes specified as a union of simpler shapes
+///
+/// The collision shape for arbitrary triangle meshes can probably in general be
+///well approximated by a compound ODE geometry object, which is merely a combination
+///of many primitives (capsule, sphere, box). I eventually want to add the ability
+///to associate compound geometry objects with Blender gameobjects. I think one
+///way of doing this would be to add a new button in the GameButtons, "RigidBodyCompound".
+///If the object is "Dynamic" + "RigidBody", then the object's bounding volume (sphere,
+///box) is created. If an object is "Dynamic" + "RigidBodyCompound", then the object itself
+///will merely create a "wrapper" compound object, with the actual geometry objects
+///being created from the object's children in Blender. E.g. if I wanted to make a
+///compound collision object consisting of a sphere and 2 boxes, I would create a
+///parent gameobject with the actual triangle mesh, and set its GameButtons to
+///"RigidBodyCompound". I would then create 3 children of this object, 1 sphere and
+///2 boxes, and set the GameButtons for the children to be "RigidBody". Then at
+///scene conversion time, the scene converter sees "RigidBodyCompound" for the
+///top-level object, then appropriately traverses the children and creates the compound
+///collision geometry consisting of 2 boxes and a sphere. In this way, arbitrary
+///mesh-mesh collision becomes much less necessary - the artist can (or must,
+///depending on your point of view!) approximate the collision shape for arbitrary
+///meshes with a combination of one or more primitive shapes. I think using the
+///parent/child relationship in Blender and a new button "RigidBodyCompound" for the
+///parent object of a compound is a feasible way of doing this in Blender.
+///
+///See ODE demo test_boxstack and look at the code when you drop a compound object
+///with the "X" key.
+///
+/// \todo add visual specification of constraints
+///
+/// extend the armature constraint system. by using empties and constraining one empty
+/// to "copy location" of another, you can get a p2p constraint between the two empties.
+/// by making the two empties each a parent of a blender object, you effectively have
+/// a p2p constraint between 2 blender bodies. the scene converter can detect these
+/// empties, detect the constraint, and generate an ODE constraint.
+///
+/// then add a new constraint type "hinge" and "slider" to correspond to ODE joints.
+/// e.g. a slider would be a constraint which restricts the axis of its object to lie
+/// along the same line as another axis of a different object. e.g. you constrain x-axis
+/// of one empty to lie along the same line as the z-axis of another empty; this gives
+/// a slider joint.
+///
+/// open questions: how to handle powered joints? to what extent should/must constraints
+/// be enforced during modeling? use CCD-style algorithm in modeler to enforce constraints?
+/// how about ODE powered constraints e.g. motors?
+///
+/// \todo enable suspension of bodies
+/// ODE offers native support for suspending dynas. but what about suspending non-dynas
+/// (e.g. geoms)? suspending geoms is also necessary to ease the load of ODE's (simple?)
+/// collision detector. suspending dynas and geoms is important for the activity culling,
+/// which apparently works at a simple level. perhaps suspension should actually
+/// remove or insert geoms/dynas into the ODE space/world? is this operation (insertion/
+/// removal) fast enough at run-time? test it. if fast enough, then suspension=remove from
+/// ODE simulation, awakening=insertion into ODE simulation.
+///
+/// \todo python interface for tweaking constraints via python
+///
+/// \todo raytesting to support gameengine sensors that need it
+///
+/// \todo investigate compatibility issues with old Blender 2.25 physics engine (sumo/fuzzics)
+/// is it possible to have compatibility? how hard is it? how important is it?
+
+
+ODEPhysicsController::ODEPhysicsController(bool dyna, bool fullRigidBody,
+ bool phantom, class PHY_IMotionState* motionstate, struct dxSpace* space,
+ struct dxWorld* world, float mass,float friction,float restitution,
+ bool implicitsphere,float center[3],float extents[3],float radius)
+ :
+ m_OdeDyna(dyna),
+ m_firstTime(true),
+ m_bFullRigidBody(fullRigidBody),
+ m_bPhantom(phantom),
+ m_bKinematic(false),
+ m_bPrevKinematic(false),
+ m_MotionState(motionstate),
+ m_OdeSuspendDynamics(false),
+ m_space(space),
+ m_world(world),
+ m_mass(mass),
+ m_friction(friction),
+ m_restitution(restitution),
+ m_bodyId(0),
+ m_geomId(0),
+ m_implicitsphere(implicitsphere),
+ m_radius(radius)
+{
+ m_center[0] = center[0];
+ m_center[1] = center[1];
+ m_center[2] = center[2];
+ m_extends[0] = extents[0];
+ m_extends[1] = extents[1];
+ m_extends[2] = extents[2];
+};
+
+
+ODEPhysicsController::~ODEPhysicsController()
+{
+ if (m_geomId)
+ {
+ dGeomDestroy (m_geomId);
+ }
+}
+
+float ODEPhysicsController::getMass()
+{
+ dMass mass;
+ dBodyGetMass(m_bodyId,&mass);
+ return mass.mass;
+}
+
+//////////////////////////////////////////////////////////////////////
+/// \todo Impart some extra impulse to dynamic objects when they collide with kinematically controlled "static" objects (ODE geoms), by using last 2 frames as 1st order approximation to the linear/angular velocity, and computing an appropriate impulse. Sumo (old physics engine) did this, see for details.
+/// \todo handle scaling of static ODE geoms or fail with error message if Ipo tries to change scale of a static geom object
+
+bool ODEPhysicsController::SynchronizeMotionStates(float time)
+{
+ /**
+ 'Late binding' of the rigidbody, because the World Scaling is not available until the scenegraph is traversed
+ */
+
+
+ if (m_firstTime)
+ {
+ m_firstTime=false;
+
+ m_MotionState->calculateWorldTransformations();
+
+ dQuaternion worldquat;
+ float worldpos[3];
+
+#ifdef dDOUBLE
+ m_MotionState->getWorldOrientation((float)worldquat[1],
+ (float)worldquat[2],(float)worldquat[3],(float)worldquat[0]);
+#else
+ m_MotionState->getWorldOrientation(worldquat[1],
+ worldquat[2],worldquat[3],worldquat[0]);
+#endif
+ m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
+
+ float scaling[3];
+ m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]);
+
+ if (!m_bPhantom)
+ {
+ if (m_implicitsphere)
+ {
+ m_geomId = dCreateSphere (m_space,m_radius*scaling[0]);
+ } else
+ {
+ m_geomId = dCreateBox (m_space, m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]);
+ }
+ } else
+ {
+ m_geomId=0;
+ }
+
+ if (m_geomId)
+ dGeomSetData(m_geomId,this);
+
+ if (!this->m_OdeDyna)
+ {
+ if (!m_bPhantom)
+ {
+ dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]);
+ dMatrix3 R;
+ dQtoR (worldquat, R);
+ dGeomSetRotation (this->m_geomId,R);
+ }
+ } else
+ {
+ //it's dynamic, so create a 'model'
+ m_bodyId = dBodyCreate(this->m_world);
+ dBodySetPosition (m_bodyId,worldpos[0],worldpos[1],worldpos[2]);
+ dBodySetQuaternion (this->m_bodyId,worldquat);
+ //this contains both scalar mass and inertia tensor
+ dMass m;
+ float length=1,width=1,height=1;
+ dMassSetBox (&m,1,m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]);
+ dMassAdjust (&m,this->m_mass);
+ dBodySetMass (m_bodyId,&m);
+
+ if (!m_bPhantom)
+ {
+ dGeomSetBody (m_geomId,m_bodyId);
+ }
+
+
+ }
+
+ if (this->m_OdeDyna && !m_bFullRigidBody)
+ {
+ // ?? huh? what to do here?
+ }
+ }
+
+
+
+ if (m_OdeDyna)
+ {
+ if (this->m_OdeSuspendDynamics)
+ {
+ return false;
+ }
+
+ const float* worldPos = (float *)dBodyGetPosition(m_bodyId);
+ m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
+
+ const float* worldquat = (float *)dBodyGetQuaternion(m_bodyId);
+ m_MotionState->setWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]);
+ }
+ else {
+ // not a dyna, so dynamics (i.e. this controller) has not updated
+ // anything. BUT! an Ipo or something else might have changed the
+ // position/orientation of this geometry.
+ // so update the static geom position
+
+ /// \todo impart some extra impulse to colliding objects!
+ dQuaternion worldquat;
+ float worldpos[3];
+
+#ifdef dDOUBLE
+ m_MotionState->getWorldOrientation((float)worldquat[1],
+ (float)worldquat[2],(float)worldquat[3],(float)worldquat[0]);
+#else
+ m_MotionState->getWorldOrientation(worldquat[1],
+ worldquat[2],worldquat[3],worldquat[0]);
+#endif
+ m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
+
+ float scaling[3];
+ m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]);
+
+ /// \todo handle scaling! what if Ipo changes scale of object?
+ // Must propagate to geom... is scaling geoms possible with ODE? Also
+ // what about scaling trimeshes, that is certainly difficult...
+ dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]);
+ dMatrix3 R;
+ dQtoR (worldquat, R);
+ dGeomSetRotation (this->m_geomId,R);
+ }
+
+ return false; //it update the worldpos
+}
+
+PHY_IMotionState* ODEPhysicsController::GetMotionState()
+{
+ return m_MotionState;
+}
+
+
+// kinematic methods
+void ODEPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
+{
+
+}
+void ODEPhysicsController::RelativeRotate(const float drot[9],bool local)
+{
+}
+void ODEPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
+{
+
+ dQuaternion worldquat;
+ worldquat[0] = quatReal;
+ worldquat[1] = quatImag0;
+ worldquat[2] = quatImag1;
+ worldquat[3] = quatImag2;
+
+ if (!this->m_OdeDyna)
+ {
+ dMatrix3 R;
+ dQtoR (worldquat, R);
+ dGeomSetRotation (this->m_geomId,R);
+ } else
+ {
+ dBodySetQuaternion (m_bodyId,worldquat);
+ this->m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
+ }
+
+}
+
+void ODEPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
+{
+ float q[4];
+ this->m_MotionState->getWorldOrientation(q[0],q[1],q[2],q[3]);
+ quatImag0=q[0];
+ quatImag1=q[1];
+ quatImag2=q[2];
+ quatReal=q[3];
+}
+
+void ODEPhysicsController::getPosition(PHY__Vector3& pos) const
+{
+ m_MotionState->getWorldPosition(pos[0],pos[1],pos[2]);
+
+}
+
+void ODEPhysicsController::setPosition(float posX,float posY,float posZ)
+{
+ if (!m_bPhantom)
+ {
+ if (!this->m_OdeDyna)
+ {
+ dGeomSetPosition (m_geomId, posX, posY, posZ);
+ } else
+ {
+ dBodySetPosition (m_bodyId, posX, posY, posZ);
+ }
+ }
+}
+void ODEPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
+{
+}
+
+// physics methods
+void ODEPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
+{
+ if (m_OdeDyna) {
+ if(local) {
+ dBodyAddRelTorque(m_bodyId, torqueX, torqueY, torqueZ);
+ } else {
+ dBodyAddTorque (m_bodyId, torqueX, torqueY, torqueZ);
+ }
+ }
+}
+
+void ODEPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
+{
+ if (m_OdeDyna) {
+ if(local) {
+ dBodyAddRelForce(m_bodyId, forceX, forceY, forceZ);
+ } else {
+ dBodyAddForce (m_bodyId, forceX, forceY, forceZ);
+ }
+ }
+}
+
+void ODEPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
+{
+ if (m_OdeDyna) {
+ if(local) {
+ // TODO: translate angular vel into local frame, then apply
+ } else {
+ dBodySetAngularVel (m_bodyId, ang_velX,ang_velY,ang_velZ);
+ }
+ }
+}
+
+void ODEPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
+{
+ if (m_OdeDyna)
+ {
+ dVector3 vel = {lin_velX,lin_velY,lin_velZ, 1.0};
+ if (local)
+ {
+ dMatrix3 worldmat;
+ dVector3 localvel;
+ dQuaternion worldquat;
+
+#ifdef dDOUBLE
+ m_MotionState->getWorldOrientation((float)worldquat[1],
+ (float)worldquat[2], (float)worldquat[3],(float)worldquat[0]);
+#else
+ m_MotionState->getWorldOrientation(worldquat[1],worldquat[2],
+ worldquat[3],worldquat[0]);
+#endif
+ dQtoR (worldquat, worldmat);
+
+ dMULTIPLY0_331 (localvel,worldmat,vel);
+ dBodySetLinearVel (m_bodyId, localvel[0],localvel[1],localvel[2]);
+
+ } else
+ {
+ dBodySetLinearVel (m_bodyId, lin_velX,lin_velY,lin_velZ);
+ }
+ }
+}
+
+void ODEPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
+{
+ if (m_OdeDyna)
+ {
+ //apply linear and angular effect
+ const dReal* linvel = dBodyGetLinearVel(m_bodyId);
+ float mass = getMass();
+ if (mass >= 0.00001f)
+ {
+ float massinv = 1.f/mass;
+ float newvel[3];
+ newvel[0]=linvel[0]+impulseX*massinv;
+ newvel[1]=linvel[1]+impulseY*massinv;
+ newvel[2]=linvel[2]+impulseZ*massinv;
+ dBodySetLinearVel(m_bodyId,newvel[0],newvel[1],newvel[2]);
+
+ const float* worldPos = (float *)dBodyGetPosition(m_bodyId);
+
+ const float* angvelc = (float *)dBodyGetAngularVel(m_bodyId);
+ float angvel[3];
+ angvel[0]=angvelc[0];
+ angvel[1]=angvelc[1];
+ angvel[2]=angvelc[2];
+
+ dVector3 impulse;
+ impulse[0]=impulseX;
+ impulse[1]=impulseY;
+ impulse[2]=impulseZ;
+
+ dVector3 ap;
+ ap[0]=attachX-worldPos[0];
+ ap[1]=attachY-worldPos[1];
+ ap[2]=attachZ-worldPos[2];
+
+ dCROSS(angvel,+=,ap,impulse);
+ dBodySetAngularVel(m_bodyId,angvel[0],angvel[1],angvel[2]);
+
+ }
+
+ }
+
+}
+
+void ODEPhysicsController::SuspendDynamics()
+{
+
+}
+
+void ODEPhysicsController::RestoreDynamics()
+{
+
+}
+
+
+/**
+ reading out information from physics
+*/
+void ODEPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
+{
+ if (m_OdeDyna)
+ {
+ const float* vel = (float *)dBodyGetLinearVel(m_bodyId);
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ } else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+
+ }
+}
+/**
+ GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+*/
+void ODEPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
+{
+
+}
+
+
+void ODEPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
+{
+
+}
+void ODEPhysicsController::setRigidBody(bool rigid)
+{
+
+}
+
+
+void ODEPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
+{
+ m_MotionState = motionstate;
+ m_bKinematic = false;
+ m_bPrevKinematic = false;
+ m_firstTime = true;
+}
+
+
+void ODEPhysicsController::SetSimulatedTime(float time)
+{
+}
+
+
+void ODEPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
+{
+
+}
+#endif
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h
new file mode 100644
index 00000000000..544d11da2ca
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/OdePhysicsController.h
@@ -0,0 +1,164 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __ODE_PHYSICSCONTROLLER_H
+#define __ODE_PHYSICSCONTROLLER_H
+
+
+#include "PHY_IPhysicsController.h"
+
+/**
+ ODE Physics Controller, a special kind of a PhysicsController.
+ A Physics Controller is a special kind of Scene Graph Transformation Controller.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changes.
+*/
+
+class ODEPhysicsController : public PHY_IPhysicsController
+
+{
+
+ bool m_OdeDyna;
+
+public:
+ ODEPhysicsController(
+ bool dyna,
+ bool fullRigidBody,
+ bool phantom,
+ class PHY_IMotionState* motionstate,
+ struct dxSpace* space,
+ struct dxWorld* world,
+ float mass,
+ float friction,
+ float restitution,
+ bool implicitsphere,
+ float center[3],
+ float extends[3],
+ float radius);
+
+ virtual ~ODEPhysicsController();
+
+ // kinematic methods
+ virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
+ virtual void RelativeRotate(const float drot[9],bool local);
+ virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
+ virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
+ virtual void setPosition(float posX,float posY,float posZ);
+ virtual void getPosition(PHY__Vector3& pos) const;
+
+ virtual void setScaling(float scaleX,float scaleY,float scaleZ);
+
+ // physics methods
+ virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local);
+ virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local);
+ virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
+ virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
+ virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
+ virtual void SetActive(bool active){};
+ virtual void SuspendDynamics();
+ virtual void RestoreDynamics();
+ virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
+ {
+ //todo ?
+ }
+
+
+ /**
+ reading out information from physics
+ */
+ virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ);
+ /**
+ GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+ */
+ virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
+ virtual float getMass();
+ virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
+ virtual void setRigidBody(bool rigid);
+
+
+ virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
+
+ // \todo remove next line !
+ virtual void SetSimulatedTime(float time);
+
+
+ virtual void WriteDynamicsToMotionState() {};
+ virtual void WriteMotionStateToDynamics(bool nondynaonly);
+ virtual class PHY_IMotionState* GetMotionState();
+
+ /**
+ call from Scene Graph Node to 'update'.
+ */
+ virtual bool SynchronizeMotionStates(float time);
+
+ virtual void calcXform(){}
+ virtual void SetMargin(float margin) {}
+ virtual float GetMargin() const {return 0.f;}
+ virtual float GetRadius() const {return 0.f;}
+ virtual void SetRadius(float margin) {}
+
+ // clientinfo for raycasts for example
+ virtual void* getNewClientInfo() { return m_clientInfo;}
+ virtual void setNewClientInfo(void* clientinfo) {m_clientInfo = clientinfo;};
+ void* m_clientInfo;
+
+ struct dxBody* GetOdeBodyId() { return m_bodyId; }
+
+ float getFriction() { return m_friction;}
+ float getRestitution() { return m_restitution;}
+
+ float GetLinVelocityMin() const { return 0.f; }
+ void SetLinVelocityMin(float val) { }
+ float GetLinVelocityMax() const { return 0.f; }
+ void SetLinVelocityMax(float val) { }
+
+
+private:
+
+ bool m_firstTime;
+ bool m_bFullRigidBody;
+ bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver'
+
+ // data to calculate fake velocities for kinematic objects (non-dynas)
+ bool m_bKinematic;
+ bool m_bPrevKinematic;
+
+
+ float m_lastTime;
+ bool m_OdeSuspendDynamics;
+ class PHY_IMotionState* m_MotionState;
+
+ //Ode specific members
+ struct dxBody* m_bodyId;
+ struct dxGeom* m_geomId;
+ struct dxSpace* m_space;
+ struct dxWorld* m_world;
+ float m_mass;
+ float m_friction;
+ float m_restitution;
+ bool m_implicitsphere;
+ float m_center[3];
+ float m_extends[3];
+ float m_radius;
+};
+
+#endif //__ODE_PHYSICSCONTROLLER_H
+
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
new file mode 100644
index 00000000000..54e97858b7f
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
@@ -0,0 +1,277 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "OdePhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+#include "OdePhysicsController.h"
+
+#include <ode/ode.h>
+#include <../ode/src/joint.h>
+#include <ode/odemath.h>
+
+ODEPhysicsEnvironment::ODEPhysicsEnvironment()
+{
+ m_OdeWorld = dWorldCreate();
+ m_OdeSpace = dHashSpaceCreate();
+ m_OdeContactGroup = dJointGroupCreate (0);
+ dWorldSetCFM (m_OdeWorld,1e-5f);
+
+ m_JointGroup = dJointGroupCreate(0);
+
+ setFixedTimeStep(true,1.f/60.f);
+}
+
+
+
+ODEPhysicsEnvironment::~ODEPhysicsEnvironment()
+{
+ dJointGroupDestroy (m_OdeContactGroup);
+ dJointGroupDestroy (m_JointGroup);
+
+ dSpaceDestroy (m_OdeSpace);
+ dWorldDestroy (m_OdeWorld);
+}
+
+
+
+void ODEPhysicsEnvironment::setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)
+{
+ m_useFixedTimeStep = useFixedTimeStep;
+
+ if (useFixedTimeStep)
+ {
+ m_fixedTimeStep = fixedTimeStep;
+ } else
+ {
+ m_fixedTimeStep = 0.f;
+ }
+ m_currentTime = 0.f;
+
+ //todo:implement fixed timestepping
+
+}
+float ODEPhysicsEnvironment::getFixedTimeStep()
+{
+ return m_fixedTimeStep;
+}
+
+
+
+bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1,float interval)
+{
+
+ float deltaTime = timeStep1;
+ int numSteps = 1;
+
+ if (m_useFixedTimeStep)
+ {
+ m_currentTime += timeStep1;
+ // equal to subSampling (might be a little smaller).
+ numSteps = (int)(m_currentTime / m_fixedTimeStep);
+ m_currentTime -= m_fixedTimeStep * (float)numSteps;
+ deltaTime = m_fixedTimeStep;
+ //todo: experiment by smoothing the remaining time over the substeps
+ }
+
+ for (int i=0;i<numSteps;i++)
+ {
+ // ode collision update
+ dSpaceCollide (m_OdeSpace,this,&ODEPhysicsEnvironment::OdeNearCallback);
+
+ int m_odeContacts = GetNumOdeContacts();
+
+ //physics integrator + resolver update
+ //dWorldStep (m_OdeWorld,deltaTime);
+ //dWorldQuickStep (m_OdeWorld,deltaTime);
+ //dWorldID w, dReal stepsize)
+
+ //clear collision points
+ this->ClearOdeContactGroup();
+ }
+ return true;
+}
+
+void ODEPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+ dWorldSetGravity (m_OdeWorld,x,y,z);
+}
+
+
+
+int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ)
+{
+
+ int constraintid = 0;
+ ODEPhysicsController* dynactrl = (ODEPhysicsController*)ctrl;
+ ODEPhysicsController* dynactrl2 = (ODEPhysicsController*)ctrl2;
+
+ switch (type)
+ {
+ case PHY_POINT2POINT_CONSTRAINT:
+ {
+ if (dynactrl)
+ {
+ dJointID jointid = dJointCreateBall (m_OdeWorld,m_JointGroup);
+ struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
+ struct dxBody* bodyid2=0;
+ const dReal* pos = dBodyGetPosition(bodyid1);
+ const dReal* R = dBodyGetRotation(bodyid1);
+ dReal offset[3] = {pivotX,pivotY,pivotZ};
+ dReal newoffset[3];
+ dMULTIPLY0_331 (newoffset,R,offset);
+ newoffset[0] += pos[0];
+ newoffset[1] += pos[1];
+ newoffset[2] += pos[2];
+
+
+ if (dynactrl2)
+ bodyid2 = dynactrl2->GetOdeBodyId();
+
+ dJointAttach (jointid, bodyid1, bodyid2);
+
+ dJointSetBallAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
+
+ constraintid = (int) jointid;
+ }
+ break;
+ }
+ case PHY_LINEHINGE_CONSTRAINT:
+ {
+ if (dynactrl)
+ {
+ dJointID jointid = dJointCreateHinge (m_OdeWorld,m_JointGroup);
+ struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
+ struct dxBody* bodyid2=0;
+ const dReal* pos = dBodyGetPosition(bodyid1);
+ const dReal* R = dBodyGetRotation(bodyid1);
+ dReal offset[3] = {pivotX,pivotY,pivotZ};
+ dReal axisset[3] = {axisX,axisY,axisZ};
+
+ dReal newoffset[3];
+ dReal newaxis[3];
+ dMULTIPLY0_331 (newaxis,R,axisset);
+
+ dMULTIPLY0_331 (newoffset,R,offset);
+ newoffset[0] += pos[0];
+ newoffset[1] += pos[1];
+ newoffset[2] += pos[2];
+
+
+ if (dynactrl2)
+ bodyid2 = dynactrl2->GetOdeBodyId();
+
+ dJointAttach (jointid, bodyid1, bodyid2);
+
+ dJointSetHingeAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
+ dJointSetHingeAxis(jointid,newaxis[0],newaxis[1],newaxis[2]);
+
+ constraintid = (int) jointid;
+ }
+ break;
+ }
+ default:
+ {
+ //not yet
+ }
+ }
+
+ return constraintid;
+
+}
+
+void ODEPhysicsEnvironment::removeConstraint(void *constraintid)
+{
+ if (constraintid)
+ {
+ dJointDestroy((dJointID) constraintid);
+ }
+}
+
+PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
+{
+
+ //m_OdeWorld
+ //collision detection / raytesting
+ return NULL;
+}
+
+
+void ODEPhysicsEnvironment::OdeNearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+ // \todo if this is a registered collision sensor
+ // fire the callback
+
+ int i;
+ // if (o1->body && o2->body) return;
+ ODEPhysicsEnvironment* env = (ODEPhysicsEnvironment*) data;
+ dBodyID b1,b2;
+
+ b1 = dGeomGetBody(o1);
+ b2 = dGeomGetBody(o2);
+ // exit without doing anything if the two bodies are connected by a joint
+ if (b1 && b2 && dAreConnected (b1,b2)) return;
+
+ ODEPhysicsController * ctrl1 =(ODEPhysicsController *)dGeomGetData(o1);
+ ODEPhysicsController * ctrl2 =(ODEPhysicsController *)dGeomGetData(o2);
+ float friction=ctrl1->getFriction();
+ float restitution = ctrl1->getRestitution();
+ //for friction, take minimum
+
+ friction=(friction < ctrl2->getFriction() ?
+ friction :ctrl2->getFriction());
+
+ //restitution:take minimum
+ restitution = restitution < ctrl2->getRestitution()?
+ restitution : ctrl2->getRestitution();
+
+ dContact contact[3]; // up to 3 contacts per box
+ for (i=0; i<3; i++) {
+ contact[i].surface.mode = dContactBounce; //dContactMu2;
+ contact[i].surface.mu = friction;//dInfinity;
+ contact[i].surface.mu2 = 0;
+ contact[i].surface.bounce = restitution;//0.5;
+ contact[i].surface.bounce_vel = 0.1f;
+ contact[i].surface.slip1=0.0;
+ }
+
+ if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
+ // dMatrix3 RI;
+ // dRSetIdentity (RI);
+ // const dReal ss[3] = {0.02,0.02,0.02};
+ for (i=0; i<numc; i++) {
+ dJointID c = dJointCreateContact (env->m_OdeWorld,env->m_OdeContactGroup,contact+i);
+ dJointAttach (c,b1,b2);
+ }
+ }
+}
+
+
+void ODEPhysicsEnvironment::ClearOdeContactGroup()
+{
+ dJointGroupEmpty (m_OdeContactGroup);
+}
+
+int ODEPhysicsEnvironment::GetNumOdeContacts()
+{
+ return m_OdeContactGroup->num;
+}
+
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
new file mode 100644
index 00000000000..54e4f7f90e1
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * The contents of this file may be used under the terms of either the GNU
+ * General Public License Version 2 or later (the "GPL", see
+ * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
+ * later (the "BL", see http://www.blender.org/BL/ ) which has to be
+ * bought from the Blender Foundation to become active, in which case the
+ * above mentioned GPL option does not apply.
+ *
+ * The Original Code is Copyright (C) 2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef _ODEPHYSICSENVIRONMENT
+#define _ODEPHYSICSENVIRONMENT
+
+
+#include "PHY_IPhysicsEnvironment.h"
+
+/**
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+class ODEPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+ bool m_useFixedTimeStep;
+ float m_fixedTimeStep;
+ float m_currentTime;
+
+public:
+ ODEPhysicsEnvironment();
+ virtual ~ODEPhysicsEnvironment();
+ virtual void beginFrame() {}
+ virtual void endFrame() {}
+
+
+// Perform an integration step of duration 'timeStep'.
+ virtual bool proceedDeltaTime(double curTime,float timeStep,float interval);
+ virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
+ virtual float getFixedTimeStep();
+
+ virtual void setGravity(float x,float y,float z);
+ virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ);
+
+ virtual void removeConstraint(void * constraintid);
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
+
+
+ //gamelogic callbacks
+ virtual void addSensor(PHY_IPhysicsController* ctrl) {}
+ virtual void removeSensor(PHY_IPhysicsController* ctrl) {}
+ virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
+ {
+ }
+ virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl) {return false;}
+ virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl) {return false;}
+ virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;}
+ virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;}
+
+
+
+ struct dxWorld* GetOdeWorld() { return m_OdeWorld; };
+ struct dxSpace* GetOdeSpace() { return m_OdeSpace;};
+
+private:
+
+
+ // ODE physics response
+ struct dxWorld* m_OdeWorld;
+ // ODE collision detection
+ struct dxSpace* m_OdeSpace;
+ void ClearOdeContactGroup();
+ struct dxJointGroup* m_OdeContactGroup;
+ struct dxJointGroup* m_JointGroup;
+
+ static void OdeNearCallback(void *data, struct dxGeom* o1, struct dxGeom* o2);
+ int GetNumOdeContacts();
+
+};
+
+#endif //_ODEPHYSICSENVIRONMENT
+
diff --git a/source/gameengine/Physics/BlOde/SConscript b/source/gameengine/Physics/BlOde/SConscript
new file mode 100644
index 00000000000..90e949d2d86
--- /dev/null
+++ b/source/gameengine/Physics/BlOde/SConscript
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+Import ('user_options_dict')
+Import ('library_env')
+
+phy_ode_env = library_env.Copy ()
+
+source_files = ['OdePhysicsController.cpp',
+ 'OdePhysicsEnvironment.cpp']
+
+phy_ode_env.Append (CPPPATH=['.',
+ '../common',
+ ])
+phy_ode_env.Append (CPPPATH=user_options_dict['ODE_INCLUDE'])
+
+phy_ode_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/PHY_Ode', source=source_files)
diff --git a/source/gameengine/Physics/Dummy/Makefile b/source/gameengine/Physics/Dummy/Makefile
index c016a0bebcb..b0c1b855322 100644
--- a/source/gameengine/Physics/Dummy/Makefile
+++ b/source/gameengine/Physics/Dummy/Makefile
@@ -39,7 +39,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../../Physics/common
CPPFLAGS += -I../../Physics/Dummy
diff --git a/source/gameengine/Physics/Makefile b/source/gameengine/Physics/Makefile
index da0d4cafd2e..b192e497f35 100644
--- a/source/gameengine/Physics/Makefile
+++ b/source/gameengine/Physics/Makefile
@@ -32,6 +32,7 @@ include nan_definitions.mk
SOURCEDIR = source/gameengine/Physics
DIR = $(OCGDIR)/gameengine/blphys
-DIRS = common Dummy Bullet
+DIRS = common Sumo Dummy Bullet
+#DIRS += BlOde
include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/CMakeLists.txt b/source/gameengine/Physics/Sumo/CMakeLists.txt
new file mode 100644
index 00000000000..c57a4af6706
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/CMakeLists.txt
@@ -0,0 +1,46 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+SET(SRC
+ SumoPHYCallbackBridge.cpp
+ SumoPhysicsController.cpp
+ SumoPhysicsEnvironment.cpp
+ Fuzzics/src/SM_FhObject.cpp
+ Fuzzics/src/SM_Object.cpp
+ Fuzzics/src/SM_Scene.cpp
+ Fuzzics/src/SM_MotionState.cpp
+)
+
+SET(INC
+ .
+ ../common
+ Fuzzics/include
+ ../../../../intern/moto/include
+ ../../../../extern/solid
+)
+
+BLENDERLIB(bf_sumo "${SRC}" "${INC}")
+#env.BlenderLib ( 'bf_sumo', sources, incs, [], libtype=['game2','player'], priority=[30, 70] , compileflags=cflags)
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
new file mode 100644
index 00000000000..5ed2c31a1d0
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/gameengine/Physics/Sumo/Fuzzics
+DIRS = src
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
new file mode 100644
index 00000000000..42b5ab48ab6
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
@@ -0,0 +1,11 @@
+#ifndef SM_CALLBACK_H
+#define SM_CALLBACK_H
+
+class SM_Callback {
+public:
+ virtual void do_me() = 0;
+ virtual ~SM_Callback() {}
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
new file mode 100644
index 00000000000..6749e7957ec
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
@@ -0,0 +1,16 @@
+#ifndef __SM_CLIENTOBJECT_INFO_H
+#define __SM_CLIENTOBJECT_INFO_H
+
+/**
+ * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
+ */
+
+struct SM_ClientObjectInfo
+{
+ int m_type;
+ void* m_clientobject1;
+ void* m_auxilary_info;
+};
+
+#endif //__SM_CLIENTOBJECT_INFO_H
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h
new file mode 100644
index 00000000000..48d5906e53d
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h
@@ -0,0 +1,26 @@
+
+
+#ifndef __SM_DEBUG_H__
+#define __SM_DEBUG_H__
+
+/* Comment this to disable all SUMO debugging printfs */
+
+#define SM_DEBUG
+
+#ifdef SM_DEBUG
+
+#include <stdio.h>
+
+/* Uncomment this to printf all ray casts */
+//#define SM_DEBUG_RAYCAST
+
+/* Uncomment this to printf collision callbacks */
+//#define SM_DEBUG_BOING
+
+/* Uncomment this to printf Xform matrix calculations */
+//#define SM_DEBUG_XFORM
+
+#endif /* SM_DEBUG */
+
+#endif /* __SM_DEBUG_H__ */
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
new file mode 100644
index 00000000000..b03612ed15e
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
@@ -0,0 +1,56 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef SM_FHOBJECT_H
+#define SM_FHOBJECT_H
+
+#include "SM_Object.h"
+
+class SM_FhObject : public SM_Object {
+public:
+ virtual ~SM_FhObject();
+ SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object);
+
+ const MT_Vector3& getRay() const { return m_ray; }
+ MT_Point3 getSpot() const { return getPosition() + m_ray; }
+ const MT_Vector3& getRayDirection() const { return m_ray_direction; }
+ SM_Object *getParentObject() const { return m_parent_object; }
+
+ static DT_Bool ray_hit(void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data);
+
+private:
+ MT_Vector3 m_ray;
+ MT_Vector3 m_ray_direction;
+ SM_Object *m_parent_object;
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
new file mode 100644
index 00000000000..fdc45af5225
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
@@ -0,0 +1,77 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef SM_MOTIONSTATE_H
+#define SM_MOTIONSTATE_H
+
+#include "MT_Transform.h"
+
+class SM_MotionState {
+public:
+ SM_MotionState() :
+ m_time(0.0),
+ m_pos(0.0, 0.0, 0.0),
+ m_orn(0.0, 0.0, 0.0, 1.0),
+ m_lin_vel(0.0, 0.0, 0.0),
+ m_ang_vel(0.0, 0.0, 0.0)
+ {}
+
+ void setPosition(const MT_Point3& pos) { m_pos = pos; }
+ void setOrientation(const MT_Quaternion& orn) { m_orn = orn; }
+ void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; }
+ void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; }
+ void setTime(MT_Scalar time) { m_time = time; }
+
+ const MT_Point3& getPosition() const { return m_pos; }
+ const MT_Quaternion& getOrientation() const { return m_orn; }
+ const MT_Vector3& getLinearVelocity() const { return m_lin_vel; }
+ const MT_Vector3& getAngularVelocity() const { return m_ang_vel; }
+
+ MT_Scalar getTime() const { return m_time; }
+
+ void integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel);
+ void integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel);
+ void integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state);
+
+ void lerp(const SM_MotionState &prev, const SM_MotionState &next);
+ void lerp(MT_Scalar t, const SM_MotionState &other);
+
+ virtual MT_Transform getTransform() const {
+ return MT_Transform(m_pos, m_orn);
+ }
+
+protected:
+ MT_Scalar m_time;
+ MT_Point3 m_pos;
+ MT_Quaternion m_orn;
+ MT_Vector3 m_lin_vel;
+ MT_Vector3 m_ang_vel;
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
new file mode 100644
index 00000000000..2d748a0f251
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
@@ -0,0 +1,393 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef SM_OBJECT_H
+#define SM_OBJECT_H
+
+#include <vector>
+
+#include <SOLID/SOLID.h>
+
+#include "SM_Callback.h"
+#include "SM_MotionState.h"
+#include <stdio.h>
+
+class SM_FhObject;
+
+/** Properties of dynamic objects */
+struct SM_ShapeProps {
+ MT_Scalar m_mass; ///< Total mass
+ MT_Scalar m_radius; ///< Bound sphere size
+ MT_Vector3 m_inertia; ///< Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; ///< Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; ///< Angular drag
+ MT_Scalar m_friction_scaling[3]; ///< Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; ///< Should I do anisotropic friction?
+ bool m_do_fh; ///< Should the object have a linear Fh spring?
+ bool m_do_rot_fh; ///< Should the object have an angular Fh spring?
+};
+
+
+/** Properties of collidable objects (non-ghost objects) */
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; ///< restitution of energy after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; ///< Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; ///< Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; ///< Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; ///< The range above the surface where Fh is active.
+ bool m_fh_normal; ///< Should the object slide off slopes?
+};
+
+class SM_ClientObject
+{
+public:
+ SM_ClientObject() {}
+ virtual ~SM_ClientObject() {}
+
+ virtual bool hasCollisionCallback() = 0;
+};
+
+/**
+ * SM_Object is an internal part of the Sumo physics engine.
+ *
+ * It encapsulates an object in the physics scene, and is responsible
+ * for calculating the collision response of objects.
+ */
+class SM_Object
+{
+public:
+ SM_Object() ;
+ SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent
+ );
+ virtual ~SM_Object();
+
+ bool isDynamic() const;
+
+ /* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+
+ void suspend(void);
+ void resume(void);
+
+ void suspendDynamics();
+
+ void restoreDynamics();
+
+ bool isGhost() const;
+
+ void suspendMaterial();
+
+ void restoreMaterial();
+
+ SM_FhObject *getFhObject() const;
+
+ void registerCallback(SM_Callback& callback);
+
+ void calcXform();
+ void notifyClient();
+ void updateInvInertiaTensor();
+
+
+ // Save the current state information for use in the
+ // velocity computation in the next frame.
+
+ void proceedKinematic(MT_Scalar timeStep);
+
+ void saveReactionForce(MT_Scalar timeStep) ;
+
+ void clearForce() ;
+
+ void clearMomentum() ;
+
+ void setMargin(MT_Scalar margin) ;
+
+ MT_Scalar getMargin() const ;
+
+ const SM_MaterialProps *getMaterialProps() const ;
+
+ const SM_ShapeProps *getShapeProps() const ;
+
+ void setPosition(const MT_Point3& pos);
+ void setOrientation(const MT_Quaternion& orn);
+ void setScaling(const MT_Vector3& scaling);
+
+ /**
+ * set an external velocity. This velocity complements
+ * the physics velocity. So setting it does not override the
+ * physics velocity. It is your responsibility to clear
+ * this external velocity. This velocity is not subject to
+ * friction or damping.
+ */
+ void setExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+ void addExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+
+ /** Override the physics velocity */
+ void addLinearVelocity(const MT_Vector3& lin_vel);
+ void setLinearVelocity(const MT_Vector3& lin_vel);
+
+ /**
+ * Set an external angular velocity. This velocity complemetns
+ * the physics angular velocity so does not override it. It is
+ * your responsibility to clear this velocity. This velocity
+ * is not subject to friction or damping.
+ */
+ void setExternalAngularVelocity(const MT_Vector3& ang_vel) ;
+ void addExternalAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Override the physics angular velocity */
+ void addAngularVelocity(const MT_Vector3& ang_vel);
+ void setAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Clear the external velocities */
+ void clearCombinedVelocities();
+
+ /**
+ * Tell the physics system to combine the external velocity
+ * with the physics velocity.
+ */
+ void resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+ ) ;
+
+
+
+ MT_Scalar getInvMass() const;
+
+ const MT_Vector3& getInvInertia() const ;
+
+ const MT_Matrix3x3& getInvInertiaTensor() const;
+
+ void applyForceField(const MT_Vector3& accel) ;
+
+ void applyCenterForce(const MT_Vector3& force) ;
+
+ void applyTorque(const MT_Vector3& torque) ;
+
+ /**
+ * Apply an impulse to the object. The impulse will be split into
+ * angular and linear components.
+ * @param attach point to apply the impulse to (in world coordinates)
+ */
+ void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) ;
+
+ /**
+ * Applies an impulse through the center of this object. (ie the angular
+ * velocity will not change.
+ */
+ void applyCenterImpulse(const MT_Vector3& impulse);
+ /**
+ * Applies an angular impulse.
+ */
+ void applyAngularImpulse(const MT_Vector3& impulse);
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const;
+ MT_Point3 getLocalCoord(const MT_Point3& world) const;
+
+ MT_Vector3 getVelocity(const MT_Point3& local) const;
+
+
+ const MT_Vector3& getReactionForce() const ;
+
+ void getMatrix(double *m) const ;
+
+ const double *getMatrix() const ;
+
+ // Still need this???
+ const MT_Transform& getScaledTransform() const;
+
+ DT_ObjectHandle getObjectHandle() const ;
+ DT_ShapeHandle getShapeHandle() const ;
+
+ SM_Object *getDynamicParent() ;
+
+ void integrateForces(MT_Scalar timeStep);
+ void integrateMomentum(MT_Scalar timeSteo);
+
+ void setRigidBody(bool is_rigid_body) ;
+
+ bool isRigidBody() const ;
+
+ // This is the callback for handling collisions of dynamic objects
+ static
+ DT_Bool
+ boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+ );
+
+ static
+ DT_Bool
+ fix(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+ );
+
+
+ SM_ClientObject *getClientObject() { return m_client_object; }
+ void setClientObject(SM_ClientObject *client_object) { m_client_object = client_object; }
+ void setPhysicsClientObject(void* physicsClientObject)
+ {
+ m_physicsClientObject = physicsClientObject;
+ }
+ void* getPhysicsClientObject() {
+ return m_physicsClientObject;
+ }
+ void relax();
+
+ SM_MotionState &getCurrentFrame();
+ SM_MotionState &getPreviousFrame();
+ SM_MotionState &getNextFrame();
+
+ const SM_MotionState &getCurrentFrame() const;
+ const SM_MotionState &getPreviousFrame() const;
+ const SM_MotionState &getNextFrame() const;
+
+ // Motion state functions
+ const MT_Point3& getPosition() const;
+ const MT_Quaternion& getOrientation() const;
+ const MT_Vector3& getLinearVelocity() const;
+ const MT_Vector3& getAngularVelocity() const;
+
+ MT_Scalar getTime() const;
+
+ void setTime(MT_Scalar time);
+
+ void interpolate(MT_Scalar timeStep);
+ void endFrame();
+
+private:
+ friend class Contact;
+ // Tweak parameters
+ static MT_Scalar ImpulseThreshold;
+
+ // return the actual linear_velocity of this object this
+ // is the addition of m_combined_lin_vel and m_lin_vel.
+
+ const
+ MT_Vector3
+ actualLinVelocity(
+ ) const ;
+
+ const
+ MT_Vector3
+ actualAngVelocity(
+ ) const ;
+
+ void dynamicCollision(const MT_Point3 &local2,
+ const MT_Vector3 &normal,
+ MT_Scalar dist,
+ const MT_Vector3 &rel_vel,
+ MT_Scalar restitution,
+ MT_Scalar friction_factor,
+ MT_Scalar invMass
+ );
+
+ typedef std::vector<SM_Callback *> T_CallbackList;
+
+
+ T_CallbackList m_callbackList; // Each object can have multiple callbacks from the client (=game engine)
+ SM_Object *m_dynamicParent; // Collisions between parent and children are ignored
+
+ // as the collision callback now has only information
+ // on an SM_Object, there must be a way that the SM_Object client
+ // can identify it's clientdata after a collision
+ SM_ClientObject *m_client_object;
+
+ void* m_physicsClientObject;
+
+ DT_ShapeHandle m_shape; // Shape for collision detection
+
+ // Material and shape properties are not owned by this class.
+
+ const SM_MaterialProps *m_materialProps;
+ const SM_MaterialProps *m_materialPropsBackup; // Backup in case the object temporarily becomes a ghost.
+ const SM_ShapeProps *m_shapeProps;
+ const SM_ShapeProps *m_shapePropsBackup; // Backup in case the object's dynamics is temporarily suspended
+ DT_ObjectHandle m_object; // A handle to the corresponding object in SOLID.
+ MT_Scalar m_margin; // Offset for the object's shape (also for collision detection)
+ MT_Vector3 m_scaling; // Non-uniform scaling of the object's shape
+
+ double m_ogl_matrix[16]; // An OpenGL-type 4x4 matrix
+ MT_Transform m_xform; // The object's local coordinate system
+ MT_Transform m_prev_xform; // The object's local coordinate system in the previous frame
+ SM_MotionState m_prev_state; // The object's motion state in the previous frame
+ MT_Scalar m_timeStep; // The duration of the last frame
+
+ MT_Vector3 m_reaction_impulse; // The accumulated impulse resulting from collisions
+ MT_Vector3 m_reaction_force; // The reaction force derived from the reaction impulse
+
+ MT_Vector3 m_lin_mom; // Linear momentum (linear velocity times mass)
+ MT_Vector3 m_ang_mom; // Angular momentum (angualr velocity times inertia)
+ MT_Vector3 m_force; // Force on center of mass (afffects linear momentum)
+ MT_Vector3 m_torque; // Torque around center of mass (affects angular momentum)
+
+ SM_MotionState m_frames[3];
+
+ MT_Vector3 m_error; // Error in position:- amount object must be moved to prevent intersection with scene
+
+ // Here are the values of externally set linear and angular
+ // velocity. These are updated from the outside
+ // (actuators and python) each frame and combined with the
+ // physics values. At the end of each frame (at the end of a
+ // call to proceed) they are set to zero. This allows the
+ // outside world to contribute to the velocity of an object
+ // but still have it react to physics.
+
+ MT_Vector3 m_combined_lin_vel;
+ MT_Vector3 m_combined_ang_vel;
+
+ // The force and torque are the accumulated forces and torques applied by the client (game logic, python).
+
+ SM_FhObject *m_fh_object; // The ray object used for Fh
+ bool m_suspended; // Is this object frozen?
+
+ // Mass properties
+ MT_Scalar m_inv_mass; // 1/mass
+ MT_Vector3 m_inv_inertia; // [1/inertia_x, 1/inertia_y, 1/inertia_z]
+ MT_Matrix3x3 m_inv_inertia_tensor; // Inverse Inertia Tensor
+
+ bool m_kinematic; // Have I been displaced (translated, rotated, scaled) in this frame?
+ bool m_prev_kinematic; // Have I been displaced (translated, rotated, scaled) in the previous frame?
+ bool m_is_rigid_body; // Should friction give me a change in angular momentum?
+ int m_static; // temporarily static.
+
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
new file mode 100644
index 00000000000..81b4cb55b45
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
@@ -0,0 +1,58 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef SM_PROPSH
+#define SM_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct SM_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //SM_PROPSH
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
new file mode 100644
index 00000000000..3d8eef2bae0
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
@@ -0,0 +1,172 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef SM_SCENE_H
+#define SM_SCENE_H
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif
+
+#include <vector>
+#include <set>
+#include <utility> //needed for pair
+
+#include <SOLID/SOLID.h>
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+#include "SM_Object.h"
+
+enum
+{
+ FH_RESPONSE,
+ SENSOR_RESPONSE, /* Touch Sensors */
+ CAMERA_RESPONSE, /* Visibility Culling */
+ OBJECT_RESPONSE, /* Object Dynamic Geometry Response */
+ STATIC_RESPONSE, /* Static Geometry Response */
+
+ NUM_RESPONSE
+};
+
+class SM_Scene {
+public:
+ SM_Scene();
+
+ ~SM_Scene();
+
+ DT_RespTableHandle getRespTableHandle() const {
+ return m_respTable;
+ }
+
+ const MT_Vector3& getForceField() const {
+ return m_forceField;
+ }
+
+ MT_Vector3& getForceField() {
+ return m_forceField;
+ }
+
+ void setForceField(const MT_Vector3& forceField) {
+ m_forceField = forceField;
+ }
+
+ void addTouchCallback(int response_class, DT_ResponseCallback callback, void *user);
+
+ void addSensor(SM_Object& object);
+ void add(SM_Object& object);
+ void remove(SM_Object& object);
+
+ void notifyCollision(SM_Object *obj1, SM_Object *obj2);
+
+ void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable);
+ DT_RespTableHandle getSecondaryRespTable() { return m_secondaryRespTable; }
+
+ void requestCollisionCallback(SM_Object &object);
+
+ void beginFrame();
+ void endFrame();
+
+ // Perform an integration step of duration 'timeStep'.
+ // 'subSampling' is the maximum duration of a substep, i.e.,
+ // The maximum time interval between two collision checks.
+ // 'subSampling' can be used to control aliasing effects
+ // (fast moving objects traversing through walls and such).
+ bool proceed(MT_Scalar curtime, MT_Scalar ticrate);
+ void proceed(MT_Scalar subStep);
+
+ /**
+ * Test whether any objects lie on the line defined by from and
+ * to. The search returns the first such bject starting at from,
+ * or NULL if there was none.
+ * @returns A reference to the object, or NULL if there was none.
+ * @param ignore_client Do not look for collisions with this
+ * object. This can be useful to avoid self-hits if
+ * starting from the location of an object.
+ * @param from The start point, in world coordinates, of the search.
+ * @param to The end point, in world coordinates, of the search.
+ * @param result A store to return the point where intersection
+ * took place (if there was an intersection).
+ * @param normal A store to return the normal of the hit object on
+ * the location of the intersection, if it took place.
+ */
+ SM_Object *rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const;
+
+private:
+
+ // Clear the user set velocities.
+ void clearObjectCombinedVelocities();
+ // This is the callback for handling collisions of dynamic objects
+ static
+ DT_Bool
+ boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+ );
+
+ /** internal type */
+ typedef std::vector<SM_Object *> T_ObjectList;
+
+ /** Handle to the scene in SOLID */
+ DT_SceneHandle m_scene;
+ /** Following response table contains the callbacks for the dynmics */
+ DT_RespTableHandle m_respTable;
+ DT_ResponseClass m_ResponseClass[NUM_RESPONSE];
+ /**
+ * Following response table contains callbacks for the client (=
+ * game engine) */
+ DT_RespTableHandle m_secondaryRespTable; // Handle
+ DT_ResponseClass m_secondaryResponseClass[NUM_RESPONSE];
+
+ /**
+ * Following resposne table contains callbacks for fixing the simulation
+ * ie making sure colliding objects do not intersect.
+ */
+ DT_RespTableHandle m_fixRespTable;
+ DT_ResponseClass m_fixResponseClass[NUM_RESPONSE];
+
+ /** The acceleration from the force field */
+ MT_Vector3 m_forceField;
+
+ /**
+ * The list of objects that receive motion updates and do
+ * collision tests. */
+ T_ObjectList m_objectList;
+
+ unsigned int m_frames;
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
new file mode 100644
index 00000000000..672dff39028
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
@@ -0,0 +1,25 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+DIR = $(OCGDIR)/sumo
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)particle $(DIR)/$(DEBUG_DIR)particle0
+
+include nan_compile.mk
+
+CPPFLAGS = -I../../include -I../include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+clean::
+ @$(RM) $(DIR)/particle $(DIR)/particle0
+ @$(RM) $(DIR)/debug/particle $(DIR)/debug/particle0
+
+LDFLAGS = -L$(DIR) -L/usr/X11R6/lib
+OGL_LDLIBS = -lglut -lGLU -lGL -pthread
+LDLIBS = -lfuzzics -lsolid $(NAN_MOTO)/lib/libmoto.a $(OGL_LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle: particle.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle0: particle0.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
new file mode 100644
index 00000000000..d7aca326b42
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
@@ -0,0 +1,709 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+#include "SM_Scene.h"
+
+#include <SOLID/SOLID.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.02;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.1, // linear drag
+ 0.1, // angular drag
+ { 1.0, 0.0, 0.0 }, // anisotropic friction
+ false, // do anisotropic friction?
+ true, // do fh?
+ true // do rot fh?
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 10.0, // Fh spring constant
+ 1.0, // Fh damping
+ 0.5, // Fh distance
+ true // Fh leveling
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ if (m_gl_shape) {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+ }
+
+ void print_reaction_force() const {
+ std::cout << m_object.getReactionForce() << std::endl;
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(&m[4]);
+ }
+
+ MT_Vector3 getUp() {
+ return MT_Vector3(&m[8]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ const MT_Point3& getPosition() {
+ return m_object.getPosition();
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ MT_Vector3 getAngularVelocity() const {
+ return m_object.getAngularVelocity();
+ }
+
+ void setMatrix() {
+ m_object.calcXform();
+ m_object.getMatrix(m);
+ }
+
+ const double *getMatrix() {
+ m_object.calcXform();
+ return m_object.getMatrix();
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Scene g_scene;
+
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+ m_object.print_reaction_force();
+}
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+ sm_ground.setMargin(ground_margin);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 0, 0);
+
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+
+ glColor3f(1, 1, 0);
+ glBegin(GL_LINES);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glVertex3d(g_spot[0] + g_normal[0],
+ g_spot[1] + g_normal[1],
+ g_spot[2] + g_normal[2]);
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.setOrientation(MT_Quaternion::random());
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ display();
+ g_hit = false;
+}
+
+
+void turn_left() {
+ object.applyTorque(5.0 * object.getUp());
+}
+
+void turn_right() {
+ object.applyTorque(-5.0 * object.getUp());
+}
+
+void forward() {
+ object.applyCenterForce(10.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-10.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
new file mode 100644
index 00000000000..cdf0a2d8f64
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
@@ -0,0 +1,695 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+
+#include "solid.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.04;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.9, // linear drag
+ 0.9 // angular drag
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 0.0, // spring constant
+ 0.0 // damping
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(-m[8], -m[9], -m[10]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ void setMatrix() {
+ m_object.getMatrix(m);
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+}
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Object sm_ray(DT_Ray(0.0, -1.0, 0.0), 0, 0, 0);
+
+static SM_Scene g_scene;
+
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+ sm_ground.setMargin(ground_margin);
+
+ new(&object) Object(&gl_sphere, sm_sphere);
+
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ MT_Vector3 normal(0, 1, 0);
+
+ MT_Point3 from = object.getWorldCoord(MT_Point3(0, 0, 0));
+ MT_Point3 to = from - normal * 10.0;
+
+ g_hit = DT_ObjectRayTest(sm_ground.getObjectHandle(),
+ from.getValue(),
+ to.getValue(), g_spot.getValue(),
+ g_normal.getValue());
+
+ // Scrap
+#define DO_FH
+#ifdef DO_FH
+ MT_Scalar dist = MT_distance(from, g_spot);
+ if (dist < 5.0) {
+ MT_Vector3 lin_vel = object.getLinearVelocity();
+ MT_Scalar lin_vel_normal = lin_vel.dot(normal);
+
+ MT_Scalar spring_extent = dist + lin_vel_normal * (timeStep * 0.5);
+
+ MT_Scalar f_spring = (5.0 - spring_extent) * 3.0;
+ object.applyCenterForce(normal * f_spring);
+ object.applyCenterForce(-lin_vel_normal * normal);
+ }
+
+#endif
+
+
+ display();
+}
+
+
+void turn_left() {
+ object.applyTorque(MT_Vector3(0.0, 10.0, 0.0));
+}
+
+void turn_right() {
+ object.applyTorque(MT_Vector3(0.0, -10.0, 0.0));
+}
+
+void forward() {
+ object.applyCenterForce(20.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-20.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
new file mode 100644
index 00000000000..b2744c5496a
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
@@ -0,0 +1,14 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+LIBNAME = fuzzics
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../include -I$(NAN_MOTO)/include -I../../include
+CPPFLAGS += -I$(NAN_SOLID)/include
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
new file mode 100644
index 00000000000..d866cdb4922
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
@@ -0,0 +1,180 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "SM_FhObject.h"
+#include "MT_MinMax.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SM_FhObject::SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object) :
+ SM_Object(rayshape, NULL, NULL, NULL),
+ m_ray(ray),
+ m_ray_direction(ray.normalized()),
+ m_parent_object(parent_object)
+{
+}
+
+SM_FhObject::~SM_FhObject()
+{
+ DT_DeleteShape(getShapeHandle());
+}
+
+DT_Bool SM_FhObject::ray_hit(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data)
+{
+
+ SM_FhObject *fh_object = dynamic_cast<SM_FhObject *>((SM_Object *)client_object2);
+ if (!fh_object)
+ {
+ std::swap(client_object1, client_object2);
+ fh_object = dynamic_cast<SM_FhObject *>((SM_Object *)client_object2);
+ }
+
+ SM_Object *hit_object = (SM_Object *)client_object1;
+ const SM_MaterialProps *matProps = hit_object->getMaterialProps();
+
+ if ((matProps == 0) || (matProps->m_fh_distance < MT_EPSILON)) {
+ return DT_CONTINUE;
+ }
+
+ SM_Object *cl_object = fh_object->getParentObject();
+
+ assert(fh_object);
+
+ if (hit_object == cl_object) {
+ // Shot myself in the foot...
+ return DT_CONTINUE;
+ }
+
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ // Exit if the client object is not dynamic.
+ if (shapeProps == 0) {
+ return DT_CONTINUE;
+ }
+
+ MT_Point3 lspot;
+ MT_Vector3 normal;
+
+ DT_Vector3 from, to, dnormal;
+ DT_Scalar dlspot;
+ fh_object->getPosition().getValue(from);
+ fh_object->getSpot().getValue(to);
+
+
+ if (DT_ObjectRayCast(hit_object->getObjectHandle(),
+ from,
+ to,
+ 1.,
+ &dlspot,
+ dnormal)) {
+
+ lspot = fh_object->getPosition() + (fh_object->getSpot() - fh_object->getPosition()) * dlspot;
+ const MT_Vector3& ray_dir = fh_object->getRayDirection();
+ MT_Scalar dist = MT_distance(fh_object->getPosition(), lspot) -
+ cl_object->getMargin() - shapeProps->m_radius;
+
+ normal = MT_Vector3(dnormal).safe_normalized();
+
+ if (dist < matProps->m_fh_distance) {
+
+ if (shapeProps->m_do_fh) {
+ lspot -= hit_object->getPosition();
+ MT_Vector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocity(lspot);
+ MT_Scalar rel_vel_ray = ray_dir.dot(rel_vel);
+ MT_Scalar spring_extent = 1.0 - dist / matProps->m_fh_distance;
+
+ MT_Scalar i_spring = spring_extent * matProps->m_fh_spring;
+ MT_Scalar i_damp = rel_vel_ray * matProps->m_fh_damping;
+
+ cl_object->addLinearVelocity(-(i_spring + i_damp) * ray_dir);
+ if (matProps->m_fh_normal) {
+ cl_object->addLinearVelocity(
+ (i_spring + i_damp) *
+ (normal - normal.dot(ray_dir) * ray_dir));
+ }
+
+ MT_Vector3 lateral = rel_vel - rel_vel_ray * ray_dir;
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ if (shapeProps->m_do_anisotropic) {
+ MT_Matrix3x3 lcs(cl_object->getOrientation());
+ MT_Vector3 loc_lateral = lateral * lcs;
+ const MT_Vector3& friction_scaling =
+ shapeProps->m_friction_scaling;
+
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ lateral = lcs * loc_lateral;
+ }
+
+
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ MT_Scalar friction_factor = matProps->m_friction;
+ MT_Scalar max_friction = friction_factor * MT_max(MT_Scalar(0.0), i_spring);
+
+ MT_Scalar rel_mom_lateral = rel_vel_lateral /
+ cl_object->getInvMass();
+
+ MT_Vector3 friction =
+ (rel_mom_lateral > max_friction) ?
+ -lateral * (max_friction / rel_vel_lateral) :
+ -lateral;
+
+ cl_object->applyCenterImpulse(friction);
+ }
+ }
+
+ if (shapeProps->m_do_rot_fh) {
+ const double *ogl_mat = cl_object->getMatrix();
+ MT_Vector3 up(&ogl_mat[8]);
+ MT_Vector3 t_spring = up.cross(normal) * matProps->m_fh_spring;
+ MT_Vector3 ang_vel = cl_object->getAngularVelocity();
+
+ // only rotations that tilt relative to the normal are damped
+ ang_vel -= ang_vel.dot(normal) * normal;
+
+ MT_Vector3 t_damp = ang_vel * matProps->m_fh_damping;
+
+ cl_object->addAngularVelocity(t_spring - t_damp);
+ }
+ }
+ }
+
+ return DT_CONTINUE;
+}
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp
new file mode 100644
index 00000000000..b8f4e0c591c
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp
@@ -0,0 +1,100 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <MT_Scalar.h>
+#include <MT_Vector3.h>
+#include <MT_Quaternion.h>
+
+#include "SM_MotionState.h"
+
+void SM_MotionState::integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel)
+{
+ m_pos += (prev_state.getLinearVelocity() + velocity) * (timeStep * 0.5);
+ m_orn += (prev_state.getAngularVelocity() * prev_state.getOrientation() + ang_vel * m_orn) * (timeStep * 0.25);
+ m_orn.normalize();
+}
+
+void SM_MotionState::integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel)
+{
+ m_pos += velocity * timeStep;
+ m_orn += ang_vel * m_orn * (timeStep * 0.5);
+ m_orn.normalize();
+}
+
+void SM_MotionState::integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state)
+{
+ m_pos += prev_state.getLinearVelocity() * timeStep;
+ m_orn += prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5);
+ m_orn.normalize();
+}
+
+/*
+// Newtonian lerp: interpolate based on Newtonian motion
+void SM_MotionState::nlerp(const SM_MotionState &prev, const SM_MotionState &next)
+{
+ MT_Scalar dt = next.getTime() - prev.getTime();
+ MT_Scalar t = getTime() - prev.getTime();
+ MT_Vector3 dx = next.getPosition() - prev.getPosition();
+ MT_Vector3 a = dx/(dt*dt) - prev.getLinearVelocity()/dt;
+
+ m_pos = prev.getPosition() + prev.getLinearVelocity()*t + a*t*t;
+}
+*/
+
+void SM_MotionState::lerp(const SM_MotionState &prev, const SM_MotionState &next)
+{
+ MT_Scalar dt = next.getTime() - prev.getTime();
+ if (MT_fuzzyZero(dt))
+ {
+ *this = next;
+ return;
+ }
+
+ MT_Scalar x = (getTime() - prev.getTime())/dt;
+
+ m_pos = x*next.getPosition() + (1-x)*prev.getPosition();
+
+ m_orn = prev.getOrientation().slerp(next.getOrientation(), 1-x);
+
+ m_lin_vel = x*next.getLinearVelocity() + (1-x)*prev.getLinearVelocity();
+ m_ang_vel = x*next.getAngularVelocity() + (1-x)*prev.getAngularVelocity();
+}
+
+void SM_MotionState::lerp(MT_Scalar t, const SM_MotionState &other)
+{
+ MT_Scalar x = (t - getTime())/(other.getTime() - getTime());
+ m_pos = (1-x)*m_pos + x*other.getPosition();
+
+ m_orn = other.getOrientation().slerp(m_orn, x);
+
+ m_lin_vel = (1-x)*m_lin_vel + x*other.getLinearVelocity();
+ m_ang_vel = (1-x)*m_ang_vel + x*other.getAngularVelocity();
+
+ m_time = t;
+}
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
new file mode 100644
index 00000000000..4b2c7cae008
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
@@ -0,0 +1,1298 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The basic physics object.
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+// This warning tells us about truncation of __long__ stl-generated names.
+// It can occasionally cause DevStudio to have internal compiler warnings.
+#pragma warning( disable : 4786 )
+#endif
+
+#include "MT_assert.h"
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+#include "SM_FhObject.h"
+#include "SM_Debug.h"
+
+#include "MT_MinMax.h"
+
+MT_Scalar SM_Object::ImpulseThreshold = -1.0;
+
+struct Contact
+{
+ SM_Object *obj1;
+ SM_Object *obj2;
+ MT_Vector3 normal;
+ MT_Point3 pos;
+
+ // Sort objects by height
+ bool operator()(const Contact *a, const Contact *b)
+ {
+ return a->pos[2] < b->pos[2];
+ }
+
+ Contact(SM_Object *o1, SM_Object *o2, const MT_Vector3 nor, const MT_Point3 p)
+ : obj1(o1),
+ obj2(o2),
+ normal(nor),
+ pos(p)
+ {
+ }
+
+ Contact()
+ {
+ }
+
+ void resolve()
+ {
+ if (obj1->m_static || obj2->m_static)
+ {
+ if (obj1->isDynamic())
+ {
+ if (obj1->m_static && obj2->m_static)
+ {
+ if (obj1->m_static < obj2->m_static)
+ {
+ obj2->m_error -= normal;
+ obj2->m_static = obj1->m_static + 1;
+ }
+ else
+ {
+ obj1->m_error += normal;
+ obj1->m_static = obj2->m_static + 1;
+ }
+ }
+ else
+ {
+ if (obj1->m_static)
+ {
+ obj2->m_error -= normal;
+ obj2->m_static = obj1->m_static + 1;
+ }
+ else
+ {
+ obj1->m_error += normal;
+ obj1->m_static = obj2->m_static + 1;
+ }
+ }
+ }
+ else
+ {
+ obj2->m_error -= normal;
+ obj2->m_static = 1;
+ }
+ }
+ else
+ {
+ // This distinction between dynamic and non-dynamic objects should not be
+ // necessary. Non-dynamic objects are assumed to have infinite mass.
+ if (obj1->isDynamic()) {
+ MT_Vector3 error = normal * 0.5f;
+ obj1->m_error += error;
+ obj2->m_error -= error;
+ }
+ else {
+ // Same again but now obj1 is non-dynamic
+ obj2->m_error -= normal;
+ obj2->m_static = obj1->m_static + 1;
+ }
+ }
+
+ }
+
+
+ typedef std::set<Contact*, Contact> Set;
+};
+
+static Contact::Set contacts;
+
+SM_Object::SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent) :
+
+ m_dynamicParent(dynamicParent),
+ m_client_object(0),
+ m_physicsClientObject(0),
+ m_shape(shape),
+ m_materialProps(materialProps),
+ m_materialPropsBackup(0),
+ m_shapeProps(shapeProps),
+ m_shapePropsBackup(0),
+ m_margin(0.0),
+ m_scaling(1.0, 1.0, 1.0),
+ m_reaction_impulse(0.0, 0.0, 0.0),
+ m_reaction_force(0.0, 0.0, 0.0),
+ m_lin_mom(0.0, 0.0, 0.0),
+ m_ang_mom(0.0, 0.0, 0.0),
+ m_force(0.0, 0.0, 0.0),
+ m_torque(0.0, 0.0, 0.0),
+ m_error(0.0, 0.0, 0.0),
+ m_combined_lin_vel (0.0, 0.0, 0.0),
+ m_combined_ang_vel (0.0, 0.0, 0.0),
+ m_fh_object(0),
+ m_inv_mass(0.0),
+ m_inv_inertia(0., 0., 0.),
+ m_kinematic(false),
+ m_prev_kinematic(false),
+ m_is_rigid_body(false),
+ m_static(0)
+{
+ m_object = DT_CreateObject(this, shape);
+ m_xform.setIdentity();
+ m_xform.getValue(m_ogl_matrix);
+ if (shapeProps)
+ {
+ if (shapeProps->m_do_fh || shapeProps->m_do_rot_fh)
+ {
+ DT_Vector3 zero = {0., 0., 0.}, ray = {0.0, 0.0, -10.0};
+ m_fh_object = new SM_FhObject(DT_NewLineSegment(zero, ray), MT_Vector3(ray), this);
+ //printf("SM_Object:: WARNING! fh disabled.\n");
+ }
+ m_inv_mass = 1. / shapeProps->m_mass;
+ m_inv_inertia = MT_Vector3(1./shapeProps->m_inertia[0], 1./shapeProps->m_inertia[1], 1./shapeProps->m_inertia[2]);
+ }
+ updateInvInertiaTensor();
+ m_suspended = false;
+}
+
+
+ void
+SM_Object::
+integrateForces(
+ MT_Scalar timeStep
+){
+ if (!m_suspended) {
+ m_prev_state = getNextFrame();
+ m_prev_state.setLinearVelocity(actualLinVelocity());
+ m_prev_state.setAngularVelocity(actualAngVelocity());
+ if (isDynamic()) {
+ // Integrate momentum (forward Euler)
+ m_lin_mom += m_force * timeStep;
+ m_ang_mom += m_torque * timeStep;
+ // Drain momentum because of air/water resistance
+ m_lin_mom *= pow(m_shapeProps->m_lin_drag, timeStep);
+ m_ang_mom *= pow(m_shapeProps->m_ang_drag, timeStep);
+ // Set velocities according momentum
+ getNextFrame().setLinearVelocity(m_lin_mom * m_inv_mass);
+ getNextFrame().setAngularVelocity(m_inv_inertia_tensor * m_ang_mom);
+ }
+ }
+
+};
+
+ void
+SM_Object::
+integrateMomentum(
+ MT_Scalar timeStep
+){
+ // Integrate position and orientation
+
+ // only do it for objects with linear and/or angular velocity
+ // else clients with hierarchies may get into trouble
+ if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero())
+ {
+
+ // those MIDPOINT and BACKWARD integration methods are
+ // in this form not ok with some testfiles !
+ // For a release build please use forward euler unless completely tested
+
+//#define MIDPOINT
+//#define BACKWARD
+#ifdef MIDPOINT
+// Midpoint rule
+ getNextFrame().integrateMidpoint(timeStep, m_prev_state, actualLinVelocity(), actualAngVelocity());
+#elif defined BACKWARD
+// Backward Euler
+ getNextFrame().integrateBackward(timeStep, actualLinVelocity(), actualAngVelocity());
+#else
+// Forward Euler
+ getNextFrame().integrateForward(timeStep, m_prev_state);
+#endif
+
+ calcXform();
+ notifyClient();
+
+ }
+}
+
+/**
+ * dynamicCollision computes the response to a collision.
+ *
+ * @param local2 the contact point in local coordinates.
+ * @param normal the contact normal.
+ * @param dist the penetration depth of the contact. (unused)
+ * @param rel_vel the relative velocity of the objects
+ * @param restitution the amount of momentum conserved in the collision. Range: 0.0 - 1.0
+ * @param friction_factor the amount of friction between the two surfaces.
+ * @param invMass the inverse mass of the collision objects (1.0 / mass)
+ */
+void SM_Object::dynamicCollision(const MT_Point3 &local2,
+ const MT_Vector3 &normal,
+ MT_Scalar dist,
+ const MT_Vector3 &rel_vel,
+ MT_Scalar restitution,
+ MT_Scalar friction_factor,
+ MT_Scalar invMass
+)
+{
+ /**
+ * rel_vel_normal is the relative velocity in the contact normal direction.
+ */
+ MT_Scalar rel_vel_normal = normal.dot(rel_vel);
+
+ /**
+ * if rel_vel_normal > 0, the objects are moving apart!
+ */
+ if (rel_vel_normal < -MT_EPSILON) {
+ /**
+ * if rel_vel_normal < ImpulseThreshold, scale the restitution down.
+ * This should improve the simulation where the object is stacked.
+ */
+ restitution *= MT_min(MT_Scalar(1.0), rel_vel_normal/ImpulseThreshold);
+
+ MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal;
+
+ if (isRigidBody())
+ {
+ MT_Vector3 temp = getInvInertiaTensor() * local2.cross(normal);
+ impulse /= invMass + normal.dot(temp.cross(local2));
+
+ /**
+ * Apply impulse at the collision point.
+ * Take rotational inertia into account.
+ */
+ applyImpulse(local2 + getNextFrame().getPosition(), impulse * normal);
+ } else {
+ /**
+ * Apply impulse through object center. (no rotation.)
+ */
+ impulse /= invMass;
+ applyCenterImpulse( impulse * normal );
+ }
+
+ MT_Vector3 external = m_combined_lin_vel + m_combined_ang_vel.cross(local2);
+ MT_Vector3 lateral = rel_vel - external - normal * (rel_vel_normal - external.dot(normal));
+#if 0
+ // test - only do friction on the physics part of the
+ // velocity.
+ vel1 -= obj1->m_combined_lin_vel;
+ vel2 -= obj2->m_combined_lin_vel;
+
+ // This should look familiar....
+ rel_vel = vel2 - vel1;
+ rel_vel_normal = normal.dot(rel_vel);
+#endif
+ /**
+ * The friction part starts here!!!!!!!!
+ *
+ * Compute the lateral component of the relative velocity
+ * lateral actually points in the opposite direction, i.e.,
+ * into the direction of the friction force.
+ */
+ if (m_shapeProps->m_do_anisotropic) {
+
+ /**
+ * For anisotropic friction we scale the lateral component,
+ * rather than compute a direction-dependent fricition
+ * factor. For this the lateral component is transformed to
+ * local coordinates.
+ */
+
+ MT_Matrix3x3 lcs(getNextFrame().getOrientation());
+
+ /**
+ * We cannot use m_xform.getBasis() for the matrix, since
+ * it might contain a non-uniform scaling.
+ * OPT: it's a bit daft to compute the matrix since the
+ * quaternion itself can be used to do the transformation.
+ */
+ MT_Vector3 loc_lateral = lateral * lcs;
+
+ /**
+ * lcs is orthogonal so lcs.inversed() == lcs.transposed(),
+ * and lcs.transposed() * lateral == lateral * lcs.
+ */
+ const MT_Vector3& friction_scaling =
+ m_shapeProps->m_friction_scaling;
+
+ // Scale the local lateral...
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ // ... and transform it back to global coordinates
+ lateral = lcs * loc_lateral;
+ }
+
+ /**
+ * A tiny Coulomb friction primer:
+ * The Coulomb friction law states that the magnitude of the
+ * maximum possible friction force depends linearly on the
+ * magnitude of the normal force.
+ *
+ * \f[
+ F_max_friction = friction_factor * F_normal
+ \f]
+ *
+ * (NB: independent of the contact area!!)
+ *
+ * The friction factor depends on the material.
+ * We use impulses rather than forces but let us not be
+ * bothered by this.
+ */
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ lateral /= rel_vel_lateral;
+
+ // Compute the maximum friction impulse
+ MT_Scalar max_friction =
+ friction_factor * MT_max(MT_Scalar(0.0), impulse);
+
+ // I guess the GEN_max is not necessary, so let's check it
+
+ MT_assert(impulse >= 0.0);
+
+ /**
+ * Here's the trick. We compute the impulse to make the
+ * lateral velocity zero. (Make the objects stick together
+ * at the contact point. If this impulse is larger than
+ * the maximum possible friction impulse, then shrink its
+ * magnitude to the maximum friction.
+ */
+
+ if (isRigidBody()) {
+
+ /**
+ * For rigid bodies we take the inertia into account,
+ * since the friction impulse is going to change the
+ * angular momentum as well.
+ */
+ MT_Vector3 temp = getInvInertiaTensor() * local2.cross(lateral);
+ MT_Scalar impulse_lateral = rel_vel_lateral /
+ (invMass + lateral.dot(temp.cross(local2)));
+
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ applyImpulse(local2 + getNextFrame().getPosition(), -lateral * friction);
+ }
+ else {
+ MT_Scalar impulse_lateral = rel_vel_lateral / invMass;
+
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ applyCenterImpulse( -friction * lateral);
+ }
+
+
+ }
+
+ //calcXform();
+ //notifyClient();
+
+ }
+}
+
+static void AddCallback(SM_Scene *scene, SM_Object *obj1, SM_Object *obj2)
+{
+ // If we have callbacks on either of the client objects, do a collision test
+ // and add a callback if they intersect.
+ DT_Vector3 v;
+ if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) ||
+ (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()) &&
+ DT_GetIntersect(obj1->getObjectHandle(), obj2->getObjectHandle(), v))
+ scene->notifyCollision(obj1, obj2);
+}
+
+DT_Bool SM_Object::boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+){
+ SM_Scene *scene = (SM_Scene *)client_data;
+ SM_Object *obj1 = (SM_Object *)object1;
+ SM_Object *obj2 = (SM_Object *)object2;
+
+ // at this point it is unknown whether we are really intersecting (broad phase)
+
+ DT_Vector3 p1, p2;
+ if (!obj2->isDynamic()) {
+ std::swap(obj1, obj2);
+ }
+
+ // If one of the objects is a ghost then ignore it for the dynamics
+ if (obj1->isGhost() || obj2->isGhost()) {
+ AddCallback(scene, obj1, obj2);
+ return DT_CONTINUE;
+ }
+
+ // Objects do not collide with parent objects
+ if (obj1->getDynamicParent() == obj2 || obj2->getDynamicParent() == obj1) {
+ AddCallback(scene, obj1, obj2);
+ return DT_CONTINUE;
+ }
+
+ if (!obj2->isDynamic()) {
+ AddCallback(scene, obj1, obj2);
+ return DT_CONTINUE;
+ }
+
+ // Get collision data from SOLID
+ if (!DT_GetPenDepth(obj1->getObjectHandle(), obj2->getObjectHandle(), p1, p2))
+ return DT_CONTINUE;
+
+ MT_Point3 local1(p1), local2(p2);
+ MT_Vector3 normal(local2 - local1);
+ MT_Scalar dist = normal.length();
+
+ if (dist < MT_EPSILON)
+ return DT_CONTINUE;
+
+ // Now we are definitely intersecting.
+
+ // Set callbacks for game engine.
+ if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) ||
+ (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()))
+ scene->notifyCollision(obj1, obj2);
+
+ local1 -= obj1->getNextFrame().getPosition();
+ local2 -= obj2->getNextFrame().getPosition();
+
+ // Calculate collision parameters
+ MT_Vector3 rel_vel = obj1->getVelocity(local1) - obj2->getVelocity(local2);
+
+ MT_Scalar restitution =
+ MT_min(obj1->getMaterialProps()->m_restitution,
+ obj2->getMaterialProps()->m_restitution);
+
+ MT_Scalar friction_factor =
+ MT_min(obj1->getMaterialProps()->m_friction,
+ obj2->getMaterialProps()->m_friction);
+
+ MT_Scalar invMass = obj1->getInvMass() + obj2->getInvMass();
+
+ normal /= dist;
+
+ // Calculate reactions
+ if (obj1->isDynamic())
+ obj1->dynamicCollision(local1, normal, dist, rel_vel, restitution, friction_factor, invMass);
+
+ if (obj2->isDynamic())
+ {
+ obj2->dynamicCollision(local2, -normal, dist, -rel_vel, restitution, friction_factor, invMass);
+ if (!obj1->isDynamic() || obj1->m_static)
+ obj2->m_static = obj1->m_static + 1;
+ }
+
+ return DT_CONTINUE;
+}
+
+DT_Bool SM_Object::fix(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+){
+ SM_Object *obj1 = (SM_Object *)object1;
+ SM_Object *obj2 = (SM_Object *)object2;
+
+ // If one of the objects is a ghost then ignore it for the dynamics
+ if (obj1->isGhost() || obj2->isGhost()) {
+ return DT_CONTINUE;
+ }
+
+ if (obj1->getDynamicParent() == obj2 || obj2->getDynamicParent() == obj1) {
+ return DT_CONTINUE;
+ }
+
+ if (!obj2->isDynamic()) {
+ std::swap(obj1, obj2);
+ }
+
+ if (!obj2->isDynamic()) {
+ return DT_CONTINUE;
+ }
+
+ // obj1 points to a dynamic object
+ DT_Vector3 p1, p2;
+ if (!DT_GetPenDepth(obj1->getObjectHandle(), obj2->getObjectHandle(), p1, p2))
+ return DT_CONTINUE;
+ MT_Point3 local1(p1), local2(p2);
+ // Get collision data from SOLID
+ MT_Vector3 normal(local2 - local1);
+
+ MT_Scalar dist = normal.dot(normal);
+ if (dist < MT_EPSILON || dist > obj2->m_shapeProps->m_radius*obj2->m_shapeProps->m_radius)
+ return DT_CONTINUE;
+
+
+ if ((obj1->m_static || !obj1->isDynamic()) && obj1->m_static < obj2->m_static)
+ {
+ obj2->m_static = obj1->m_static + 1;
+ } else if (obj2->m_static && obj2->m_static < obj1->m_static)
+ {
+ obj1->m_static = obj2->m_static + 1;
+ }
+
+ contacts.insert(new Contact(obj1, obj2, normal, MT_Point3(local1 + 0.5*(local2 - local1))));
+
+
+ return DT_CONTINUE;
+}
+
+void SM_Object::relax(void)
+{
+ for (Contact::Set::iterator csit = contacts.begin() ; csit != contacts.end(); ++csit)
+ {
+ (*csit)->resolve();
+ delete (*csit);
+ }
+
+ contacts.clear();
+ if (m_error.fuzzyZero())
+ return;
+ //std::cout << "SM_Object::relax: { " << m_error << " }" << std::endl;
+
+ getNextFrame().setPosition(getNextFrame().getPosition() + m_error);
+ m_error.setValue(0., 0., 0.);
+ //calcXform();
+ //notifyClient();
+}
+
+SM_Object::SM_Object() :
+ m_dynamicParent(0),
+ m_client_object(0),
+ m_physicsClientObject(0),
+ m_shape(0),
+ m_materialProps(0),
+ m_materialPropsBackup(0),
+ m_shapeProps(0),
+ m_shapePropsBackup(0),
+ m_object(0),
+ m_margin(0.0),
+ m_scaling(1.0, 1.0, 1.0),
+ m_reaction_impulse(0.0, 0.0, 0.0),
+ m_reaction_force(0.0, 0.0, 0.0),
+ m_lin_mom(0.0, 0.0, 0.0),
+ m_ang_mom(0.0, 0.0, 0.0),
+ m_force(0.0, 0.0, 0.0),
+ m_torque(0.0, 0.0, 0.0),
+ m_error(0.0, 0.0, 0.0),
+ m_combined_lin_vel (0.0, 0.0, 0.0),
+ m_combined_ang_vel (0.0, 0.0, 0.0),
+ m_fh_object(0),
+ m_kinematic(false),
+ m_prev_kinematic(false),
+ m_is_rigid_body(false)
+{
+ // warning no initialization of variables done by moto.
+}
+
+SM_Object::
+~SM_Object() {
+ if (m_fh_object)
+ delete m_fh_object;
+
+ DT_DestroyObject(m_object);
+ m_object = NULL;
+}
+
+ bool
+SM_Object::
+isDynamic(
+) const {
+ return m_shapeProps != 0;
+}
+
+/* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+ void
+SM_Object::
+suspend(
+){
+ if (!m_suspended) {
+ m_suspended = true;
+ suspendDynamics();
+ }
+}
+
+ void
+SM_Object::
+resume(
+) {
+ if (m_suspended) {
+ m_suspended = false;
+ restoreDynamics();
+ }
+}
+
+ void
+SM_Object::
+suspendDynamics(
+) {
+ if (m_shapeProps) {
+ m_shapePropsBackup = m_shapeProps;
+ m_shapeProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreDynamics(
+) {
+ if (m_shapePropsBackup) {
+ m_shapeProps = m_shapePropsBackup;
+ m_shapePropsBackup = 0;
+ }
+}
+
+ bool
+SM_Object::
+isGhost(
+) const {
+ return m_materialProps == 0;
+}
+
+ void
+SM_Object::
+suspendMaterial(
+) {
+ if (m_materialProps) {
+ m_materialPropsBackup = m_materialProps;
+ m_materialProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreMaterial(
+) {
+ if (m_materialPropsBackup) {
+ m_materialProps = m_materialPropsBackup;
+ m_materialPropsBackup = 0;
+ }
+}
+
+ SM_FhObject *
+SM_Object::
+getFhObject(
+) const {
+ return m_fh_object;
+}
+
+ void
+SM_Object::
+registerCallback(
+ SM_Callback& callback
+) {
+ m_callbackList.push_back(&callback);
+}
+
+// Set the local coordinate system according to the current state
+ void
+SM_Object::
+calcXform() {
+#ifdef SM_DEBUG_XFORM
+ printf("SM_Object::calcXform m_pos = { %-0.5f, %-0.5f, %-0.5f }\n",
+ m_pos[0], m_pos[1], m_pos[2]);
+ printf(" m_orn = { %-0.5f, %-0.5f, %-0.5f, %-0.5f }\n",
+ m_orn[0], m_orn[1], m_orn[2], m_orn[3]);
+ printf(" m_scaling = { %-0.5f, %-0.5f, %-0.5f }\n",
+ m_scaling[0], m_scaling[1], m_scaling[2]);
+#endif
+ m_xform.setOrigin(getNextFrame().getPosition());
+ m_xform.setBasis(MT_Matrix3x3(getNextFrame().getOrientation(), m_scaling));
+ m_xform.getValue(m_ogl_matrix);
+
+ /* Blender has been known to crash here.
+ This usually means SM_Object *this has been deleted more than once. */
+ DT_SetMatrixd(m_object, m_ogl_matrix);
+ if (m_fh_object) {
+ m_fh_object->setPosition(getNextFrame().getPosition());
+ m_fh_object->calcXform();
+ }
+ updateInvInertiaTensor();
+#ifdef SM_DEBUG_XFORM
+ printf("\n | %-0.5f %-0.5f %-0.5f %-0.5f |\n",
+ m_ogl_matrix[0], m_ogl_matrix[4], m_ogl_matrix[ 8], m_ogl_matrix[12]);
+ printf( " | %-0.5f %-0.5f %-0.5f %-0.5f |\n",
+ m_ogl_matrix[1], m_ogl_matrix[5], m_ogl_matrix[ 9], m_ogl_matrix[13]);
+ printf( "m_ogl_matrix = | %-0.5f %-0.5f %-0.5f %-0.5f |\n",
+ m_ogl_matrix[2], m_ogl_matrix[6], m_ogl_matrix[10], m_ogl_matrix[14]);
+ printf( " | %-0.5f %-0.5f %-0.5f %-0.5f |\n\n",
+ m_ogl_matrix[3], m_ogl_matrix[7], m_ogl_matrix[11], m_ogl_matrix[15]);
+#endif
+}
+
+ void
+SM_Object::updateInvInertiaTensor()
+{
+ m_inv_inertia_tensor = m_xform.getBasis().scaled(m_inv_inertia[0], m_inv_inertia[1], m_inv_inertia[2]) * m_xform.getBasis().transposed();
+}
+
+// Call callbacks to notify the client of a change of placement
+ void
+SM_Object::
+notifyClient() {
+ T_CallbackList::iterator i;
+ for (i = m_callbackList.begin(); i != m_callbackList.end(); ++i) {
+ (*i)->do_me();
+ }
+}
+
+
+// Save the current state information for use in the velocity computation in the next frame.
+ void
+SM_Object::
+proceedKinematic(
+ MT_Scalar timeStep
+) {
+ /* nzc: need to bunge this for the logic bubbling as well? */
+ if (!m_suspended) {
+ m_prev_kinematic = m_kinematic;
+ if (m_kinematic) {
+ m_prev_xform = m_xform;
+ m_timeStep = timeStep;
+ calcXform();
+ m_kinematic = false;
+ }
+ }
+}
+
+ void
+SM_Object::
+saveReactionForce(
+ MT_Scalar timeStep
+) {
+ if (isDynamic()) {
+ m_reaction_force = m_reaction_impulse / timeStep;
+ m_reaction_impulse.setValue(0.0, 0.0, 0.0);
+ }
+}
+
+ void
+SM_Object::
+clearForce(
+) {
+ m_force.setValue(0.0, 0.0, 0.0);
+ m_torque.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+clearMomentum(
+) {
+ m_lin_mom.setValue(0.0, 0.0, 0.0);
+ m_ang_mom.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+setMargin(
+ MT_Scalar margin
+) {
+ m_margin = margin;
+ DT_SetMargin(m_object, margin);
+}
+
+ MT_Scalar
+SM_Object::
+getMargin(
+) const {
+ return m_margin;
+}
+
+const
+ SM_MaterialProps *
+SM_Object::
+getMaterialProps(
+) const {
+ return m_materialProps;
+}
+
+const
+ SM_ShapeProps *
+SM_Object::
+getShapeProps(
+) const {
+ return m_shapeProps;
+}
+
+ void
+SM_Object::
+setPosition(
+ const MT_Point3& pos
+){
+ m_kinematic = true;
+ getNextFrame().setPosition(pos);
+ endFrame();
+}
+
+ void
+SM_Object::
+setOrientation(
+ const MT_Quaternion& orn
+){
+ MT_assert(!orn.fuzzyZero());
+ m_kinematic = true;
+ getNextFrame().setOrientation(orn);
+ endFrame();
+}
+
+ void
+SM_Object::
+setScaling(
+ const MT_Vector3& scaling
+){
+ m_kinematic = true;
+ m_scaling = scaling;
+}
+
+/**
+ * Functions to handle linear velocity
+ */
+
+ void
+SM_Object::
+setExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel=lin_vel;
+}
+
+ void
+SM_Object::
+addExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel+=lin_vel;
+}
+
+ void
+SM_Object::
+addLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ setLinearVelocity(getNextFrame().getLinearVelocity() + lin_vel);
+}
+
+ void
+SM_Object::
+setLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ getNextFrame().setLinearVelocity(lin_vel);
+ if (m_shapeProps) {
+ m_lin_mom = getNextFrame().getLinearVelocity() * m_shapeProps->m_mass;
+ }
+}
+
+/**
+ * Functions to handle angular velocity
+ */
+
+ void
+SM_Object::
+setExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel = ang_vel;
+}
+
+ void
+SM_Object::
+addExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel += ang_vel;
+}
+
+ void
+SM_Object::
+setAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ getNextFrame().setAngularVelocity(ang_vel);
+ if (m_shapeProps) {
+ m_ang_mom = getNextFrame().getAngularVelocity() * m_shapeProps->m_inertia;
+ }
+}
+
+ void
+SM_Object::
+addAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ setAngularVelocity(getNextFrame().getAngularVelocity() + ang_vel);
+}
+
+
+ void
+SM_Object::
+clearCombinedVelocities(
+) {
+ m_combined_lin_vel = MT_Vector3(0,0,0);
+ m_combined_ang_vel = MT_Vector3(0,0,0);
+}
+
+ void
+SM_Object::
+resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+) {
+
+ // Different behaviours for dynamic and non-dynamic
+ // objects. For non-dynamic we just set the velocity to
+ // zero. For dynmic the physics velocity has to be
+ // taken into account. We must make an arbitrary decision
+ // on how to resolve the 2 velocities. Choices are
+ // Add the physics velocity to the linear velocity. Objects
+ // will just keep on moving in the direction they were
+ // last set in - untill external forces affect them.
+ // Set the combinbed linear and physics velocity to zero.
+ // Set the physics velocity in the direction of the set velocity
+ // zero.
+ if (isDynamic()) {
+
+#if 1
+ getNextFrame().setLinearVelocity(getNextFrame().getLinearVelocity() + lin_vel);
+ getNextFrame().setAngularVelocity(getNextFrame().getAngularVelocity() + ang_vel);
+#else
+
+ //compute the component of the physics velocity in the
+ // direction of the set velocity and set it to zero.
+ MT_Vector3 lin_vel_norm = lin_vel.normalized();
+
+ setLinearVelocity(getNextFrame().getLinearVelocity() - (getNextFrame().getLinearVelocity().dot(lin_vel_norm) * lin_vel_norm));
+#endif
+ m_lin_mom = getNextFrame().getLinearVelocity() * m_shapeProps->m_mass;
+ m_ang_mom = getNextFrame().getAngularVelocity() * m_shapeProps->m_inertia;
+ clearCombinedVelocities();
+
+ }
+
+}
+
+
+ MT_Scalar
+SM_Object::
+getInvMass(
+) const {
+ return m_inv_mass;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ const MT_Vector3&
+SM_Object::
+getInvInertia(
+) const {
+ return m_inv_inertia;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ const MT_Matrix3x3&
+SM_Object::
+getInvInertiaTensor(
+) const {
+ return m_inv_inertia_tensor;
+}
+
+ void
+SM_Object::
+applyForceField(
+ const MT_Vector3& accel
+) {
+ if (m_shapeProps) {
+ m_force += m_shapeProps->m_mass * accel; // F = m * a
+ }
+}
+
+ void
+SM_Object::
+applyCenterForce(
+ const MT_Vector3& force
+) {
+ m_force += force;
+}
+
+ void
+SM_Object::
+applyTorque(
+ const MT_Vector3& torque
+) {
+ m_torque += torque;
+}
+
+ void
+SM_Object::
+applyImpulse(
+ const MT_Point3& attach, const MT_Vector3& impulse
+) {
+ applyCenterImpulse(impulse); // Change in linear momentum
+ applyAngularImpulse((attach - getNextFrame().getPosition()).cross(impulse)); // Change in angular momentump
+}
+
+ void
+SM_Object::
+applyCenterImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_lin_mom += impulse;
+ m_reaction_impulse += impulse;
+ getNextFrame().setLinearVelocity(m_lin_mom * m_inv_mass);
+
+ // The linear velocity is immedialtely updated since otherwise
+ // simultaneous collisions will get a double impulse.
+ }
+}
+
+ void
+SM_Object::
+applyAngularImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_ang_mom += impulse;
+ getNextFrame().setAngularVelocity( m_inv_inertia_tensor * m_ang_mom);
+ }
+}
+
+ MT_Point3
+SM_Object::
+getWorldCoord(
+ const MT_Point3& local
+) const {
+ return m_xform(local);
+}
+
+ MT_Vector3
+SM_Object::
+getVelocity(
+ const MT_Point3& local
+) const {
+ if (m_prev_kinematic && !isDynamic())
+ {
+ // For displaced objects the velocity is faked using the previous state.
+ // Dynamic objects get their own velocity, not the faked velocity.
+ // (Dynamic objects shouldn't be displaced in the first place!!)
+ return (m_xform(local) - m_prev_xform(local)) / m_timeStep;
+ }
+
+ // NB: m_xform.getBasis() * local == m_xform(local) - m_xform.getOrigin()
+ return actualLinVelocity() + actualAngVelocity().cross(local);
+}
+
+
+const
+ MT_Vector3&
+SM_Object::
+getReactionForce(
+) const {
+ return m_reaction_force;
+}
+
+ void
+SM_Object::
+getMatrix(
+ double *m
+) const {
+ std::copy(&m_ogl_matrix[0], &m_ogl_matrix[16], &m[0]);
+}
+
+const
+ double *
+SM_Object::
+getMatrix(
+) const {
+ return m_ogl_matrix;
+}
+
+// Still need this???
+const
+ MT_Transform&
+SM_Object::
+getScaledTransform(
+) const {
+ return m_xform;
+}
+
+ DT_ObjectHandle
+SM_Object::
+getObjectHandle(
+) const {
+ return m_object;
+}
+
+ DT_ShapeHandle
+SM_Object::
+getShapeHandle(
+) const {
+ return m_shape;
+}
+
+ SM_Object *
+SM_Object::
+getDynamicParent(
+) {
+ return m_dynamicParent;
+}
+
+ void
+SM_Object::
+setRigidBody(
+ bool is_rigid_body
+) {
+ m_is_rigid_body = is_rigid_body;
+}
+
+ bool
+SM_Object::
+isRigidBody(
+) const {
+ return m_is_rigid_body;
+}
+
+const
+ MT_Vector3
+SM_Object::
+actualLinVelocity(
+) const {
+ return m_combined_lin_vel + getNextFrame().getLinearVelocity();
+};
+
+const
+ MT_Vector3
+SM_Object::
+actualAngVelocity(
+) const {
+ return m_combined_ang_vel + getNextFrame().getAngularVelocity();
+}
+
+
+SM_MotionState&
+SM_Object::
+getCurrentFrame()
+{
+ return m_frames[1];
+}
+
+SM_MotionState&
+SM_Object::
+getPreviousFrame()
+{
+ return m_frames[0];
+}
+
+SM_MotionState &
+SM_Object::
+getNextFrame()
+{
+ return m_frames[2];
+}
+
+const SM_MotionState &
+SM_Object::
+getCurrentFrame() const
+{
+ return m_frames[1];
+}
+
+const SM_MotionState &
+SM_Object::
+getPreviousFrame() const
+{
+ return m_frames[0];
+}
+
+const SM_MotionState &
+SM_Object::
+getNextFrame() const
+{
+ return m_frames[2];
+}
+
+
+const MT_Point3&
+SM_Object::
+getPosition() const
+{
+ return m_frames[1].getPosition();
+}
+
+const MT_Quaternion&
+SM_Object::
+getOrientation() const
+{
+ return m_frames[1].getOrientation();
+}
+
+const MT_Vector3&
+SM_Object::
+getLinearVelocity() const
+{
+ return m_frames[1].getLinearVelocity();
+}
+
+const MT_Vector3&
+SM_Object::
+getAngularVelocity() const
+{
+ return m_frames[1].getAngularVelocity();
+}
+
+void
+SM_Object::
+interpolate(MT_Scalar timeStep)
+{
+ if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero())
+ {
+ getCurrentFrame().setTime(timeStep);
+ getCurrentFrame().lerp(getPreviousFrame(), getNextFrame());
+ notifyClient();
+ }
+}
+
+void
+SM_Object::
+endFrame()
+{
+ getPreviousFrame() = getNextFrame();
+ getCurrentFrame() = getNextFrame();
+ m_static = 0;
+}
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
new file mode 100644
index 00000000000..f0791bbf89f
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
@@ -0,0 +1,378 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#pragma warning(disable : 4786) // shut off 255 char limit debug template warning
+#endif
+
+#include "SM_Scene.h"
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+
+#include "SM_Debug.h"
+
+#include <algorithm>
+
+SM_Scene::SM_Scene() :
+ m_scene(DT_CreateScene()),
+ m_respTable(DT_CreateRespTable()),
+ m_secondaryRespTable(DT_CreateRespTable()),
+ m_fixRespTable(DT_CreateRespTable()),
+ m_forceField(0.0, 0.0, 0.0),
+ m_frames(0)
+{
+ for (int i = 0 ; i < NUM_RESPONSE; i++)
+ {
+ m_ResponseClass[i] = DT_GenResponseClass(m_respTable);
+ m_secondaryResponseClass[i] = DT_GenResponseClass(m_secondaryRespTable);
+ m_fixResponseClass[i] = DT_GenResponseClass(m_fixRespTable);
+ }
+
+ /* Sensor */
+ DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
+
+ /* Static */
+ DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[STATIC_RESPONSE], 0, DT_NO_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+
+ /* Object */
+ DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+
+ /* Fh Object */
+ DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+ DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
+
+ /* Object (Fix Pass) */
+ DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
+ DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this);
+ DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this);
+ DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
+}
+
+void SM_Scene::addTouchCallback(int response_class, DT_ResponseCallback callback, void *user)
+{
+ DT_AddClassResponse(m_secondaryRespTable, m_secondaryResponseClass[response_class], callback, DT_BROAD_RESPONSE, user);
+}
+
+void SM_Scene::addSensor(SM_Object& object)
+{
+ T_ObjectList::iterator i =
+ std::find(m_objectList.begin(), m_objectList.end(), &object);
+ if (i == m_objectList.end())
+ {
+ object.calcXform();
+ m_objectList.push_back(&object);
+ DT_AddObject(m_scene, object.getObjectHandle());
+ DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]);
+ DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass [SENSOR_RESPONSE]);
+ DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]);
+ }
+}
+
+void SM_Scene::add(SM_Object& object) {
+ object.calcXform();
+ m_objectList.push_back(&object);
+ DT_AddObject(m_scene, object.getObjectHandle());
+ if (object.isDynamic()) {
+ DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[OBJECT_RESPONSE]);
+ DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[OBJECT_RESPONSE]);
+ DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[OBJECT_RESPONSE]);
+ } else {
+ DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[STATIC_RESPONSE]);
+ DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[STATIC_RESPONSE]);
+ DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[STATIC_RESPONSE]);
+ }
+
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_AddObject(m_scene, fh_object->getObjectHandle());
+ DT_SetResponseClass(m_respTable, fh_object->getObjectHandle(), m_ResponseClass[FH_RESPONSE]);
+ DT_SetResponseClass(m_secondaryRespTable, fh_object->getObjectHandle(), m_secondaryResponseClass[FH_RESPONSE]);
+ DT_SetResponseClass(m_fixRespTable, fh_object->getObjectHandle(), m_fixResponseClass[FH_RESPONSE]);
+ }
+}
+
+void SM_Scene::requestCollisionCallback(SM_Object &object)
+{
+ DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[OBJECT_RESPONSE]);
+ DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[OBJECT_RESPONSE]);
+// DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[OBJECT_RESPONSE]);
+}
+
+void SM_Scene::remove(SM_Object& object) {
+ //std::cout << "SM_Scene::remove this =" << this << "object = " << &object << std::endl;
+ T_ObjectList::iterator i =
+ std::find(m_objectList.begin(), m_objectList.end(), &object);
+ if (!(i == m_objectList.end()))
+ {
+ std::swap(*i, m_objectList.back());
+ m_objectList.pop_back();
+ DT_RemoveObject(m_scene, object.getObjectHandle());
+
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_RemoveObject(m_scene, fh_object->getObjectHandle());
+ }
+ }
+ else {
+ // tried to remove an object that is not in the scene
+ //assert(false);
+ }
+}
+
+void SM_Scene::beginFrame()
+{
+ T_ObjectList::iterator i;
+ // Apply a forcefield (such as gravity)
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i)
+ (*i)->applyForceField(m_forceField);
+
+}
+
+void SM_Scene::endFrame()
+{
+ T_ObjectList::iterator i;
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i)
+ (*i)->clearForce();
+}
+
+bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate)
+{
+ if (!m_frames)
+ {
+ if (ticrate > 0.)
+ m_frames = (unsigned int)(curtime*ticrate) + 1.0;
+ else
+ m_frames = (unsigned int)(curtime*65536.0);
+ }
+
+ // Divide the timeStep into a number of subsamples of size roughly
+ // equal to subS (might be a little smaller).
+ MT_Scalar subStep;
+ int num_samples;
+ int frames = m_frames;
+
+ // Compute the number of steps to do this update.
+ if (ticrate > 0.0)
+ {
+ // Fixed time step
+ subStep = 1.0/ticrate;
+ num_samples = (unsigned int)(curtime*ticrate + 1.0) - m_frames;
+
+ if (num_samples > 4)
+ {
+ std::cout << "Dropping physics frames! frames:" << num_samples << " substep: " << subStep << std::endl;
+ MT_Scalar tr = ticrate;
+ do
+ {
+ frames = frames / 2;
+ tr = tr / 2.0;
+ num_samples = (unsigned int)(curtime*tr + 1.0) - frames;
+ subStep *= 2.0;
+ } while (num_samples > 8);
+ std::cout << " frames:" << num_samples << " substep: " << subStep << std::endl;
+ }
+ }
+ else
+ {
+ // Variable time step. (old update)
+ // Integrate at least 100 Hz
+ MT_Scalar timeStep = curtime - m_frames/65536.0;
+ subStep = timeStep > 0.01 ? 0.01 : timeStep;
+ num_samples = int(timeStep * 0.01);
+ if (num_samples < 1)
+ num_samples = 1;
+ }
+
+ // Do a physics timestep.
+ T_ObjectList::iterator i;
+ if (num_samples > 0)
+ {
+ // Do the integration steps per object.
+ for (int step = 0; step != num_samples; ++step)
+ {
+ MT_Scalar time;
+ if (ticrate > 0.)
+ time = MT_Scalar(frames + step + 1) * subStep;
+ else
+ time = MT_Scalar(m_frames)/65536.0 + MT_Scalar(step + 1)*subStep;
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->endFrame();
+ // Apply a forcefield (such as gravity)
+ (*i)->integrateForces(subStep);
+ // And second we update the object positions by performing
+ // an integration step for each object
+ (*i)->integrateMomentum(subStep);
+ }
+
+ // So now first we let the physics scene respond to
+ // new forces, velocities set externally.
+ // The collsion and friction impulses are computed here.
+ // Collision phase
+ DT_Test(m_scene, m_respTable);
+
+ // Contact phase
+ DT_Test(m_scene, m_fixRespTable);
+
+ // Finish this timestep by saving al state information for the next
+ // timestep and clearing the accumulated forces.
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->relax();
+ (*i)->proceedKinematic(subStep);
+ (*i)->saveReactionForce(subStep);
+ (*i)->getNextFrame().setTime(time);
+ //(*i)->clearForce();
+ }
+ }
+ }
+
+ if (ticrate > 0)
+ {
+ // Interpolate between time steps.
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i)
+ (*i)->interpolate(curtime);
+
+ //only update the m_frames after an actual physics timestep
+ if (num_samples)
+ {
+ m_frames = (unsigned int)(curtime*ticrate) + 1.0;
+ }
+ }
+ else
+ {
+ m_frames = (unsigned int)(curtime*65536.0);
+ }
+
+ return num_samples != 0;
+}
+
+void SM_Scene::notifyCollision(SM_Object *obj1, SM_Object *obj2)
+{
+ // For each pair of object that collided, call the corresponding callback.
+ if (m_secondaryRespTable)
+ DT_CallResponse(m_secondaryRespTable, obj1->getObjectHandle(), obj2->getObjectHandle(), 0);
+}
+
+
+SM_Object *SM_Scene::rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const {
+#ifdef SM_DEBUG_RAYCAST
+ std::cout << "ray: { " << from << " } - { " << to << " }" << std::endl;
+#endif
+
+ DT_Vector3 n, dfrom, dto;
+ DT_Scalar param;
+ from.getValue(dfrom);
+ to.getValue(dto);
+ SM_Object *hit_object = (SM_Object *)
+ DT_RayCast(m_scene, ignore_client, dfrom, dto, 1., &param, n);
+
+ if (hit_object) {
+ //result = hit_object->getWorldCoord(from + (to - from)*param);
+ result = from + (to - from) * param;
+ normal.setValue(n);
+#ifdef SM_DEBUG_RAYCAST
+ std::cout << "ray: { " << from << " } -> { " << to << " }: { " << result
+ << " } (" << param << "), normal = { " << normal << " }" << std::endl;
+#endif
+ }
+
+ return hit_object;
+}
+
+void SM_Scene::clearObjectCombinedVelocities() {
+
+ T_ObjectList::iterator i;
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+
+ (*i)->clearCombinedVelocities();
+
+ }
+
+}
+
+
+void SM_Scene::setSecondaryRespTable(DT_RespTableHandle secondaryRespTable) {
+ m_secondaryRespTable = secondaryRespTable;
+}
+
+
+DT_Bool SM_Scene::boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *
+){
+ SM_Scene *scene = (SM_Scene *)client_data;
+ SM_Object *obj1 = (SM_Object *)object1;
+ SM_Object *obj2 = (SM_Object *)object2;
+
+ scene->notifyCollision(obj1, obj2); // Record this collision for client callbacks
+
+#ifdef SM_DEBUG_BOING
+ printf("SM_Scene::boing\n");
+#endif
+
+ return DT_CONTINUE;
+}
+
+SM_Scene::~SM_Scene()
+{
+ //std::cout << "SM_Scene::~ SM_Scene(): destroy " << this << std::endl;
+// if (m_objectList.begin() != m_objectList.end())
+// std::cout << "SM_Scene::~SM_Scene: There are still objects in the Sumo scene!" << std::endl;
+ for (T_ObjectList::iterator it = m_objectList.begin() ; it != m_objectList.end() ; it++)
+ delete *it;
+
+ DT_DestroyRespTable(m_respTable);
+ DT_DestroyRespTable(m_secondaryRespTable);
+ DT_DestroyRespTable(m_fixRespTable);
+ DT_DestroyScene(m_scene);
+}
diff --git a/source/gameengine/Physics/Sumo/Makefile b/source/gameengine/Physics/Sumo/Makefile
new file mode 100644
index 00000000000..69efc4d84eb
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Makefile
@@ -0,0 +1,50 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+SOURCEDIR = source/gameengine/Physics/Sumo
+LIBNAME = sumo
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+DIRS = Fuzzics
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_SOLID)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/SConscript b/source/gameengine/Physics/Sumo/SConscript
new file mode 100644
index 00000000000..a228a986af2
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SConscript
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = ['SumoPHYCallbackBridge.cpp',
+ 'SumoPhysicsController.cpp',
+ 'SumoPhysicsEnvironment.cpp',
+ 'Fuzzics/src/SM_FhObject.cpp',
+ 'Fuzzics/src/SM_Object.cpp',
+ 'Fuzzics/src/SM_Scene.cpp',
+ 'Fuzzics/src/SM_MotionState.cpp'
+ ]
+
+incs =['.',
+ '../common',
+ 'Fuzzics/include',
+ '#/intern/moto/include'
+ ]
+incs += [env['BF_SOLID_INC']]
+
+cflags = []
+if env['OURPLATFORM']=='win32-vc':
+ cflags.append('/GR')
+ cflags.append('/O1')
+
+env.BlenderLib ( 'bf_sumo', sources, incs, [], libtype=['core','player'], priority=[400, 55] , compileflags=cflags)
diff --git a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp
new file mode 100644
index 00000000000..1992bbe3421
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp
@@ -0,0 +1,66 @@
+#include "SumoPHYCallbackBridge.h"
+#include "PHY_IPhysicsController.h"
+#include "SM_Object.h"
+
+
+SumoPHYCallbackBridge::SumoPHYCallbackBridge(void* clientData,PHY_ResponseCallback phyCallback)
+:m_orgClientData(clientData),
+m_phyCallback(phyCallback)
+{
+
+}
+DT_Bool SumoPHYCallbackBridge::StaticSolidToPHYCallback(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data)
+{
+ SumoPHYCallbackBridge* bridge = static_cast<SumoPHYCallbackBridge*>(client_data);
+ bridge->SolidToPHY(client_object1,client_object2,coll_data);
+ return false;
+}
+
+DT_Bool SumoPHYCallbackBridge::SolidToPHY(void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data)
+{
+
+ SM_Object* smObject1 = static_cast<SM_Object*>(client_object1);
+ SM_Object* smObject2 = static_cast<SM_Object*>(client_object2);
+
+ PHY_IPhysicsController* ctrl1 = static_cast<PHY_IPhysicsController*>(smObject1->getPhysicsClientObject());
+ PHY_IPhysicsController* ctrl2 = static_cast<PHY_IPhysicsController*>(smObject2->getPhysicsClientObject());
+
+ if (!ctrl1 || !ctrl2)
+ {
+ //todo: check which objects are not linked up properly
+ return false;
+ }
+ if (coll_data)
+ {
+ PHY_CollData phyCollData;
+
+ phyCollData.m_point1[0] = coll_data->point1[0];
+ phyCollData.m_point1[1] = coll_data->point1[1];
+ phyCollData.m_point1[2] = coll_data->point1[2];
+ phyCollData.m_point1[3] = 0.f;
+
+ phyCollData.m_point2[0] = coll_data->point2[0];
+ phyCollData.m_point2[1] = coll_data->point2[1];
+ phyCollData.m_point2[2] = coll_data->point2[2];
+ phyCollData.m_point2[3] = 0.f;
+
+ phyCollData.m_normal[0] = coll_data->normal[0];
+ phyCollData.m_normal[1] = coll_data->normal[1];
+ phyCollData.m_normal[2] = coll_data->normal[2];
+ phyCollData.m_normal[3] = 0.f;
+
+
+ return m_phyCallback(m_orgClientData,
+ ctrl1,ctrl2,&phyCollData);
+ }
+
+ return m_phyCallback(m_orgClientData,
+ ctrl1,ctrl2,0);
+
+}
+
diff --git a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h
new file mode 100644
index 00000000000..cc980f3961d
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h
@@ -0,0 +1,28 @@
+#ifndef SUMO_PHY_CALLBACK_BRIDGE_H
+#define SUMO_PHY_CALLBACK_BRIDGE_H
+
+#include <SOLID/SOLID.h>
+#include "PHY_DynamicTypes.h"
+
+class SumoPHYCallbackBridge
+{
+ void* m_orgClientData;
+ PHY_ResponseCallback m_phyCallback;
+
+public:
+
+ SumoPHYCallbackBridge(void* clientData,PHY_ResponseCallback phyCallback);
+
+ static DT_Bool StaticSolidToPHYCallback(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+ DT_Bool SolidToPHY(void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+
+};
+
+#endif //SUMO_PHY_CALLBACK_BRIDGE_H
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
new file mode 100644
index 00000000000..56caa9236bf
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
@@ -0,0 +1,495 @@
+/**
+ * @file $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "SumoPhysicsController.h"
+#include "PHY_IMotionState.h"
+#include "SM_Object.h"
+#include "MT_Quaternion.h"
+
+
+SumoPhysicsController::SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+
+ bool dyna)
+ :
+ m_sumoObj(sumoObj) ,
+ m_sumoScene(sumoScene),
+ m_bFirstTime(true),
+ m_bDyna(dyna),
+ m_MotionState(motionstate)
+{
+ if (m_sumoObj)
+ {
+
+ PHY__Vector3 pos1;
+ getPosition(pos1);
+ MT_Point3 pos(pos1);
+
+ //temp debugging check
+ //assert(pos.length() < 100000.f);
+
+ //need this to do the upcast after the solid/sumo collision callback
+ m_sumoObj->setPhysicsClientObject(this);
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+ }
+};
+
+
+
+SumoPhysicsController::~SumoPhysicsController()
+{
+ if (m_sumoObj)
+ {
+ m_sumoScene->remove(*m_sumoObj);
+
+ delete m_sumoObj;
+ m_sumoObj = NULL;
+ }
+}
+
+float SumoPhysicsController::getMass()
+{
+ if (m_sumoObj)
+ {
+ const SM_ShapeProps *shapeprops = m_sumoObj->getShapeProps();
+ if(shapeprops!=NULL) return shapeprops->m_mass;
+ }
+ return 0.f;
+}
+
+bool SumoPhysicsController::SynchronizeMotionStates(float)
+{
+ if (m_bFirstTime)
+ {
+ setSumoTransform(!m_bFirstTime);
+ m_bFirstTime = false;
+ }
+ return false;
+}
+
+
+
+
+void SumoPhysicsController::GetWorldOrientation(MT_Matrix3x3& mat)
+{
+ float orn[4];
+ m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+ MT_Quaternion quat(orn);
+ mat.setRotation(quat);
+
+}
+
+void SumoPhysicsController::getPosition(PHY__Vector3& pos) const
+{
+ assert(m_sumoObj);
+
+ pos[0] = m_sumoObj->getPosition()[0];
+ pos[1] = m_sumoObj->getPosition()[0];
+ pos[2] = m_sumoObj->getPosition()[0];
+
+ //m_MotionState->getWorldPosition(pos[0],pos[1],pos[2]);
+}
+
+void SumoPhysicsController::GetWorldPosition(MT_Point3& pos)
+{
+// assert(m_sumoObj);
+
+// pos[0] = m_sumoObj->getPosition()[0];
+// pos[1] = m_sumoObj->getPosition()[0];
+// pos[2] = m_sumoObj->getPosition()[0];
+
+ float worldpos[3];
+ m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
+ pos[0]=worldpos[0];
+ pos[1]=worldpos[1];
+ pos[2]=worldpos[2];
+}
+
+void SumoPhysicsController::GetWorldScaling(MT_Vector3& scale)
+{
+ float worldscale[3];
+ m_MotionState->getWorldScaling(worldscale[0],worldscale[1],worldscale[2]);
+ scale[0]=worldscale[0];
+ scale[1]=worldscale[1];
+ scale[2]=worldscale[2];
+}
+
+
+ // kinematic methods
+void SumoPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Matrix3x3 mat;
+ GetWorldOrientation(mat);
+ MT_Vector3 dloc(dlocX,dlocY,dlocZ);
+
+ MT_Point3 newpos = m_sumoObj->getPosition();
+
+ newpos += (local ? mat * dloc : dloc);
+ m_sumoObj->setPosition(newpos);
+ }
+
+}
+void SumoPhysicsController::RelativeRotate(const float drot[12],bool local)
+{
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 drotmat(drot);
+ MT_Matrix3x3 currentOrn;
+ GetWorldOrientation(currentOrn);
+
+ m_sumoObj->setOrientation(m_sumoObj->getOrientation()*(local ?
+ drotmat : (currentOrn.inverse() * drotmat * currentOrn)).getRotation());
+ }
+
+}
+void SumoPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
+{
+ m_sumoObj->setOrientation(MT_Quaternion(quatImag0,quatImag1,quatImag2,quatReal));
+}
+
+void SumoPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
+{
+ const MT_Quaternion& q = m_sumoObj->getOrientation();
+ quatImag0 = q[0];
+ quatImag1 = q[1];
+ quatImag2 = q[2];
+ quatReal = q[3];
+}
+
+void SumoPhysicsController::setPosition(float posX,float posY,float posZ)
+{
+ m_sumoObj->setPosition(MT_Point3(posX,posY,posZ));
+}
+
+void SumoPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
+{
+ if (!m_bDyna)
+ m_sumoObj->setScaling(MT_Vector3(scaleX,scaleY,scaleZ));
+}
+
+ // physics methods
+void SumoPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 torque(torqueX,torqueY,torqueZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->applyTorque(local ?
+ orn * torque :
+ torque);
+ }
+}
+
+void SumoPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 force(forceX,forceY,forceZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->applyCenterForce(local ?
+ orn * force :
+ force);
+ }
+}
+
+void SumoPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 ang_vel(ang_velX,ang_velY,ang_velZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->setExternalAngularVelocity(local ?
+ orn * ang_vel :
+ ang_vel);
+ }
+}
+
+void SumoPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
+{
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ MT_Vector3 lin_vel(lin_velX,lin_velY,lin_velZ);
+ m_sumoObj->setExternalLinearVelocity(local ?
+ orn * lin_vel :
+ lin_vel);
+ }
+}
+
+void SumoPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
+{
+ if (m_sumoObj)
+ m_sumoObj->resolveCombinedVelocities(MT_Vector3(linvelX,linvelY,linvelZ),MT_Vector3(angVelX,angVelY,angVelZ));
+}
+
+
+
+
+void SumoPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 attach(attachX,attachY,attachZ);
+ MT_Vector3 impulse(impulseX,impulseY,impulseZ);
+ m_sumoObj->applyImpulse(attach,impulse);
+ }
+
+}
+
+void SumoPhysicsController::SuspendDynamics()
+{
+ m_suspendDynamics=true;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->suspendDynamics();
+ m_sumoObj->setLinearVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->setAngularVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->calcXform();
+ }
+}
+
+void SumoPhysicsController::RestoreDynamics()
+{
+ m_suspendDynamics=false;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->restoreDynamics();
+ }
+}
+
+
+/**
+ reading out information from physics
+*/
+void SumoPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getLinearVelocity();
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ }
+ else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+ }
+}
+
+/**
+ GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+*/
+void SumoPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 pos(posX,posY,posZ);
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getVelocity(pos);
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ }
+ else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+
+ }
+}
+
+void SumoPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
+{
+ const MT_Vector3& force = m_sumoObj->getReactionForce();
+ forceX = force[0];
+ forceY = force[1];
+ forceZ = force[2];
+}
+
+void SumoPhysicsController::setRigidBody(bool rigid)
+{
+ m_sumoObj->setRigidBody(rigid);
+}
+
+void SumoPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
+{
+ m_MotionState = motionstate;
+
+ SM_Object* dynaparent=0;
+ SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
+
+ if (sumoparentctrl)
+ {
+ dynaparent = sumoparentctrl->GetSumoObject();
+ }
+
+ SM_Object* orgsumoobject = m_sumoObj;
+
+
+ m_sumoObj = new SM_Object(
+ orgsumoobject->getShapeHandle(),
+ orgsumoobject->getMaterialProps(),
+ orgsumoobject->getShapeProps(),
+ dynaparent);
+
+ m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
+
+ m_sumoObj->setMargin(orgsumoobject->getMargin());
+ m_sumoObj->setPosition(orgsumoobject->getPosition());
+ m_sumoObj->setOrientation(orgsumoobject->getOrientation());
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+
+ m_sumoScene->add(* (m_sumoObj));
+}
+
+PHY_IMotionState* SumoPhysicsController::GetMotionState()
+{
+ return m_MotionState;
+}
+
+void SumoPhysicsController::SetSimulatedTime(float)
+{
+}
+
+
+void SumoPhysicsController::WriteMotionStateToDynamics(bool)
+{
+
+}
+// this is the actual callback from sumo, and the position/orientation
+//is written to the scenegraph, using the motionstate abstraction
+
+void SumoPhysicsController::do_me()
+{
+ MT_assert(m_sumoObj);
+ const MT_Point3& pos = m_sumoObj->getPosition();
+ const MT_Quaternion& orn = m_sumoObj->getOrientation();
+
+ MT_assert(m_MotionState);
+ m_MotionState->setWorldPosition(pos[0],pos[1],pos[2]);
+ m_MotionState->setWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+}
+
+
+void SumoPhysicsController::setSumoTransform(bool nondynaonly)
+{
+ if (!nondynaonly || !m_bDyna)
+ {
+ if (m_sumoObj)
+ {
+ MT_Point3 pos;
+ GetWorldPosition(pos);
+
+ m_sumoObj->setPosition(pos);
+ if (m_bDyna)
+ {
+ m_sumoObj->setScaling(MT_Vector3(1,1,1));
+ } else
+ {
+ MT_Vector3 scale;
+ GetWorldScaling(scale);
+ m_sumoObj->setScaling(scale);
+ }
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->setOrientation(orn.getRotation());
+ m_sumoObj->calcXform();
+ }
+ }
+}
+
+
+ // clientinfo for raycasts for example
+void* SumoPhysicsController::getNewClientInfo()
+{
+ if (m_sumoObj)
+ return m_sumoObj->getClientObject();
+ return 0;
+
+}
+void SumoPhysicsController::setNewClientInfo(void* clientinfo)
+{
+ if (m_sumoObj)
+ {
+ SM_ClientObject* clOb = static_cast<SM_ClientObject*> (clientinfo);
+ m_sumoObj->setClientObject(clOb);
+ }
+
+}
+
+void SumoPhysicsController::calcXform()
+{
+ if (m_sumoObj)
+ m_sumoObj->calcXform();
+}
+
+void SumoPhysicsController::SetMargin(float margin)
+{
+ if (m_sumoObj)
+ m_sumoObj->setMargin(margin);
+}
+
+float SumoPhysicsController::GetMargin() const
+{
+ if (m_sumoObj)
+ m_sumoObj->getMargin();
+ return 0.f;
+}
+
+float SumoPhysicsController::GetRadius() const
+{
+ if (m_sumoObj && m_sumoObj->getShapeProps())
+ {
+ return m_sumoObj->getShapeProps()->m_radius;
+ }
+ return 0.f;
+
+}
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
new file mode 100644
index 00000000000..adf29649f18
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
@@ -0,0 +1,192 @@
+/**
+ * @file $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __SUMO_PHYSICSCONTROLLER_H
+#define __SUMO_PHYSICSCONTROLLER_H
+
+#include "PHY_IPhysicsController.h"
+#include "SM_Scene.h"
+#include "SM_Callback.h"
+
+/**
+ * Sumo Physics Controller, a special kind of a PhysicsController.
+ * A Physics Controller is a special kind of Scene Graph Transformation Controller.
+ * Each time the scene graph get's updated, the controller get's a chance
+ * in the 'Update' method to reflect changes.
+ *
+ * Sumo uses the SOLID library for collision detection.
+ */
+class SumoPhysicsController : public PHY_IPhysicsController , public SM_Callback
+
+
+{
+
+
+public:
+ SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+ bool dyna);
+
+ virtual ~SumoPhysicsController();
+
+ /**
+ * @name Kinematic Methods.
+ */
+ /*@{*/
+ virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
+ /**
+ * @param drot a 3x4 matrix. This will treated as a 3x3 rotation matrix.
+ * @warning RelativeRotate expects a 3x4 matrix. The fourth column is padding.
+ */
+ virtual void RelativeRotate(const float drot[12],bool local);
+ virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
+ virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
+ virtual void setPosition(float posX,float posY,float posZ);
+ virtual void getPosition(PHY__Vector3& pos) const;
+
+ virtual void setScaling(float scaleX,float scaleY,float scaleZ);
+ /*@}*/
+
+ /**
+ * @name Physics Methods
+ */
+ /*@{*/
+ virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local);
+ virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local);
+ virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
+ virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
+ virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
+ virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
+ virtual void SetActive(bool active){};
+ virtual void SuspendDynamics();
+ virtual void RestoreDynamics();
+ /*@}*/
+
+
+ /**
+ * reading out information from physics
+ */
+ virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ);
+ /**
+ * GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+ */
+ virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
+ virtual float getMass();
+ virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
+ virtual void setRigidBody(bool rigid);
+
+
+ virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
+
+ // TODO: remove next line !
+ virtual void SetSimulatedTime(float time);
+
+ virtual void WriteDynamicsToMotionState() {};
+ virtual void WriteMotionStateToDynamics(bool nondynaonly);
+ virtual class PHY_IMotionState* GetMotionState();
+
+ /**
+ * call from Scene Graph Node to 'update'.
+ */
+ virtual bool SynchronizeMotionStates(float time);
+
+ virtual void calcXform();
+ virtual void SetMargin(float margin) ;
+ virtual float GetMargin() const;
+ virtual float GetRadius() const ;
+ virtual void SetRadius(float margin) { SetMargin(margin); }
+
+
+ // clientinfo for raycasts for example
+ virtual void* getNewClientInfo();
+ virtual void setNewClientInfo(void* clientinfo);
+
+ float getFriction() { return m_friction;}
+ float getRestitution() { return m_restitution;}
+
+ /**
+ * Sumo callback
+ */
+ virtual void do_me();
+
+ class SM_Object* GetSumoObject ()
+ {
+ return m_sumoObj;
+ };
+
+ void GetWorldOrientation(class MT_Matrix3x3& mat);
+ void GetWorldPosition(MT_Point3& pos);
+ void GetWorldScaling(MT_Vector3& scale);
+
+ float GetLinVelocityMin() const { return 0.f; }
+ void SetLinVelocityMin(float val) { }
+ float GetLinVelocityMax() const { return 0.f; }
+ void SetLinVelocityMax(float val) { }
+
+
+// void SetSumoObject(class SM_Object* sumoObj) {
+// m_sumoObj = sumoObj;
+// }
+// void SetSumoScene(class SM_Scene* sumoScene) {
+// m_sumoScene = sumoScene;
+// }
+
+ void setSumoTransform(bool nondynaonly);
+
+
+private:
+ class SM_Object* m_sumoObj;
+ class SM_Scene* m_sumoScene; // needed for replication
+ bool m_bFirstTime;
+ bool m_bDyna;
+
+ float m_friction;
+ float m_restitution;
+
+
+ bool m_suspendDynamics;
+
+ bool m_firstTime;
+ bool m_bFullRigidBody;
+ bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver'
+
+ // data to calculate fake velocities for kinematic objects (non-dynas)
+ bool m_bKinematic;
+ bool m_bPrevKinematic;
+
+ float m_lastTime;
+
+ class PHY_IMotionState* m_MotionState;
+
+
+};
+
+#endif //__SUMO_PHYSICSCONTROLLER_H
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..b4daf0a3f80
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
@@ -0,0 +1,264 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <string.h> // memset
+#include "SumoPhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+#include "SumoPhysicsController.h"
+#include "SM_Scene.h"
+#include "SumoPHYCallbackBridge.h"
+#include <SOLID/SOLID.h>
+
+SumoPhysicsEnvironment::SumoPhysicsEnvironment()
+{
+ m_fixedTimeStep = 1.f/60.f;
+ m_useFixedTimeStep = true;
+ m_currentTime = 0.f;
+
+ m_sumoScene = new SM_Scene();
+}
+
+
+
+SumoPhysicsEnvironment::~SumoPhysicsEnvironment()
+{
+ delete m_sumoScene;
+}
+
+
+
+void SumoPhysicsEnvironment::beginFrame()
+{
+ m_sumoScene->beginFrame();
+}
+
+void SumoPhysicsEnvironment::endFrame()
+{
+ m_sumoScene->endFrame();
+}
+
+void SumoPhysicsEnvironment::setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)
+{
+ m_useFixedTimeStep = useFixedTimeStep;
+ if (m_useFixedTimeStep)
+ {
+ m_fixedTimeStep = fixedTimeStep;
+ } else
+ {
+ m_fixedTimeStep = 0.f;
+ }
+ //reset current time ?
+ m_currentTime = 0.f;
+}
+float SumoPhysicsEnvironment::getFixedTimeStep()
+{
+ return m_fixedTimeStep;
+}
+
+
+bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval)
+{
+
+ bool result = false;
+ if (m_useFixedTimeStep)
+ {
+ m_currentTime += timeStep;
+ float ticrate = 1.f/m_fixedTimeStep;
+
+ result = m_sumoScene->proceed(curTime, ticrate);
+ } else
+ {
+ m_currentTime += timeStep;
+ result = m_sumoScene->proceed(m_currentTime, timeStep);
+ }
+ return result;
+}
+
+void SumoPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+ m_sumoScene->setForceField(MT_Vector3(x,y,z));
+}
+
+int SumoPhysicsEnvironment::createConstraint(
+ class PHY_IPhysicsController* ctrl,
+ class PHY_IPhysicsController* ctrl2,
+ PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ,
+ float axis1X,float axis1Y,float axis1Z,
+ float axis2X,float axis2Y,float axis2Z,
+ int flag
+ )
+{
+ int constraintid = 0;
+ return constraintid;
+}
+
+void SumoPhysicsEnvironment::removeConstraint(int constraintid)
+{
+ if (constraintid)
+ {
+ }
+}
+
+PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,
+ float fromX,float fromY,float fromZ,
+ float toX,float toY,float toZ)
+{
+ SumoPhysicsController* ignoreCtr = static_cast<SumoPhysicsController*> (filterCallback.m_ignoreController);
+
+ //collision detection / raytesting
+ MT_Point3 hit, normal;
+ PHY_RayCastResult result;
+
+ SM_Object* sm_ignore = 0;
+ if (ignoreCtr)
+ sm_ignore = ignoreCtr->GetSumoObject();
+
+ memset(&result, 0, sizeof(result));
+
+ SM_Object* smOb = m_sumoScene->rayTest(sm_ignore,MT_Point3(fromX, fromY, fromZ),MT_Point3(toX, toY, toZ), hit, normal);
+ if (smOb)
+ {
+ result.m_controller = (PHY_IPhysicsController *) smOb->getPhysicsClientObject();
+ result.m_hitPoint[0] = hit[0];
+ result.m_hitPoint[1] = hit[1];
+ result.m_hitPoint[2] = hit[2];
+ result.m_hitNormal[0] = normal[0];
+ result.m_hitNormal[1] = normal[1];
+ result.m_hitNormal[2] = normal[2];
+ filterCallback.reportHit(&result);
+ }
+ return result.m_controller;
+}
+//gamelogic callbacks
+void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
+{
+ SumoPhysicsController* smctrl = dynamic_cast<SumoPhysicsController*>(ctrl);
+ SM_Object* smObject = smctrl->GetSumoObject();
+ assert(smObject);
+ if (smObject)
+ {
+ m_sumoScene->addSensor(*smObject);
+ }
+}
+void SumoPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
+{
+ SumoPhysicsController* smctrl = dynamic_cast<SumoPhysicsController*>(ctrl);
+ SM_Object* smObject = smctrl->GetSumoObject();
+ assert(smObject);
+ if (smObject)
+ {
+ m_sumoScene->remove(*smObject);
+ }
+}
+
+
+void SumoPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
+{
+
+ int sumoRespClass = 0;
+
+ //map PHY_ convention into SM_ convention
+ switch (response_class)
+ {
+ case PHY_FH_RESPONSE:
+ sumoRespClass = FH_RESPONSE;
+ break;
+ case PHY_SENSOR_RESPONSE:
+ sumoRespClass = SENSOR_RESPONSE;
+ break;
+ case PHY_CAMERA_RESPONSE:
+ sumoRespClass =CAMERA_RESPONSE;
+ break;
+ case PHY_OBJECT_RESPONSE:
+ sumoRespClass = OBJECT_RESPONSE;
+ break;
+ case PHY_STATIC_RESPONSE:
+ sumoRespClass = PHY_STATIC_RESPONSE;
+ break;
+ case PHY_BROADPH_RESPONSE:
+ return;
+ default:
+ assert(0);
+ return;
+ }
+
+ SumoPHYCallbackBridge* bridge = new SumoPHYCallbackBridge(user,callback);
+
+ m_sumoScene->addTouchCallback(sumoRespClass,SumoPHYCallbackBridge::StaticSolidToPHYCallback,bridge);
+}
+bool SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl)
+{
+ SumoPhysicsController* smctrl = dynamic_cast<SumoPhysicsController*>(ctrl);
+ MT_assert(smctrl);
+ SM_Object* smObject = smctrl->GetSumoObject();
+ MT_assert(smObject);
+ if (smObject)
+ {
+ //assert(smObject->getPhysicsClientObject() == ctrl);
+ smObject->setPhysicsClientObject(ctrl);
+
+ m_sumoScene->requestCollisionCallback(*smObject);
+ return true;
+ }
+ return false;
+}
+
+bool SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
+{
+ // intentionally empty
+ return false;
+}
+
+PHY_IPhysicsController* SumoPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
+{
+ DT_ShapeHandle shape = DT_NewSphere(0.0);
+ SM_Object* ob = new SM_Object(shape,0,0,0);
+ ob->setPosition(MT_Point3(position));
+ //testing
+ MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90));
+ ob->setOrientation(rotquatje);
+
+ PHY_IPhysicsController* ctrl = new SumoPhysicsController(m_sumoScene,ob,0,false);
+ ctrl->SetMargin(radius);
+ return ctrl;
+}
+PHY_IPhysicsController* SumoPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
+{
+ DT_ShapeHandle shape = DT_NewCone(coneradius,coneheight);
+ SM_Object* ob = new SM_Object(shape,0,0,0);
+ ob->setPosition(MT_Point3(0.f,0.f,0.f));
+ MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90));
+ ob->setOrientation(rotquatje);
+
+ PHY_IPhysicsController* ctrl = new SumoPhysicsController(m_sumoScene,ob,0,false);
+
+ return ctrl;
+}
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
new file mode 100644
index 00000000000..5ae33eb4b0e
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef _SUMOPhysicsEnvironment
+#define _SUMOPhysicsEnvironment
+
+#include "MT_Scalar.h"
+
+#include "PHY_IPhysicsEnvironment.h"
+class SumoPHYCallbackBridge;
+#include <vector>
+/**
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+class SumoPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+ class SM_Scene* m_sumoScene;
+ float m_currentTime;
+ float m_fixedTimeStep;
+ bool m_useFixedTimeStep;
+
+ std::vector<SumoPHYCallbackBridge*> m_callbacks;
+
+public:
+ SumoPhysicsEnvironment();
+ virtual ~SumoPhysicsEnvironment();
+ virtual void beginFrame();
+ virtual void endFrame();
+// Perform an integration step of duration 'timeStep'.
+ virtual bool proceedDeltaTime(double curTime,float timeStep,float interval);
+ virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
+ virtual float getFixedTimeStep();
+
+ virtual void setGravity(float x,float y,float z);
+ virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ,
+ float axis1X=0,float axis1Y=0,float axis1Z=0,
+ float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
+
+ );
+
+ virtual void removeConstraint(int constraintid);
+
+ //complex constraint for vehicles
+ virtual PHY_IVehicle* getVehicleConstraint(int constraintId)
+ {
+ return 0;
+ }
+
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes) { return false; }
+
+
+ //gamelogic callbacks
+ virtual void addSensor(PHY_IPhysicsController* ctrl);
+ virtual void removeSensor(PHY_IPhysicsController* ctrl);
+ virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user);
+ virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl);
+ virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl);
+ virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position);
+ virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight);
+
+ virtual float getConstraintParam(int constraintId,int param)
+ {
+ return 0.f;
+ }
+ virtual void setConstraintParam(int constraintId,int param,float value,float value1)
+ {
+ }
+ SM_Scene* GetSumoScene()
+ {
+ return m_sumoScene;
+ }
+
+protected:
+ // 60Hz (Default)
+ static MT_Scalar PhysicsTicRate;
+
+};
+
+#endif //_SUMOPhysicsEnvironment
+
diff --git a/source/gameengine/Physics/Sumo/convert.txt b/source/gameengine/Physics/Sumo/convert.txt
new file mode 100644
index 00000000000..81f8f602cde
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/convert.txt
@@ -0,0 +1,35 @@
+static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
+{
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ int numpolys = meshobj->NumPolygons();
+ int numvalidpolys = 0;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ DT_Begin();
+ for (int v=0; v<poly->VertexCount(); v++) {
+ MT_Point3 pt = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[v],
+ poly->GetMaterial()->GetPolyMaterial())->xyz();
+ DT_Vertex(pt[0],pt[1],pt[2]);
+ }
+ DT_End();
+
+ numvalidpolys++;
+ }
+ }
+
+ DT_EndComplexShape();
+
+ if (numvalidpolys==0) {
+ delete shape;
+ return NULL;
+ } else {
+ return shape;
+ }
+}
diff --git a/source/gameengine/Physics/Sumo/include/interpolator.h b/source/gameengine/Physics/Sumo/include/interpolator.h
new file mode 100644
index 00000000000..055c242edc7
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/interpolator.h
@@ -0,0 +1,27 @@
+#ifndef INTERPOLATOR_H
+#define INTERPOLATOR_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(IP_IpoHandle);
+
+typedef struct IP_ControlPoint {
+ DT_Scalar m_key;
+ DT_Scalar m_keyValue;
+} IP_ControlPoint;
+
+IP_IpoHandle IP_CreateLinear(const IP_ControlPoint *cpoints, int num_cpoints);
+
+void IP_DeleteInterpolator(IP_IpoHandle ipo);
+
+DT_Scalar IP_GetValue(IP_IpoHandle ipo, DT_Scalar key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/common/Makefile b/source/gameengine/Physics/common/Makefile
index f2dd0134b71..e3edd426c36 100644
--- a/source/gameengine/Physics/common/Makefile
+++ b/source/gameengine/Physics/common/Makefile
@@ -40,7 +40,7 @@ CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
CPPFLAGS += -I../../blender
# these two needed because of blenkernel
CPPFLAGS += -I../../blender/makesdna
diff --git a/source/gameengine/SConscript b/source/gameengine/SConscript
index 592b138583f..864e4c3ebee 100644
--- a/source/gameengine/SConscript
+++ b/source/gameengine/SConscript
@@ -18,5 +18,13 @@ SConscript(['BlenderRoutines/SConscript',
'VideoTexture/SConscript'
])
+if env['WITH_BF_SOLID']:
+ SConscript(['Physics/Sumo/SConscript'])
+
if env['WITH_BF_PLAYER']:
SConscript(['GamePlayer/SConscript'])
+
+#if user_options_dict['USE_PHYSICS'] == 'solid':
+# SConscript(['Physics/Sumo/SConscript'])
+#elif user_options_dict['USE_PHYSICS'] == 'ode':
+# SConscript(['Physics/BlOde/SConscript'])
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
index 6d26e5b6d35..6b23105a278 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
@@ -81,17 +81,17 @@ static int setColor (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
return -1;
}
// set color
- getFilter(self)->setColor((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
- (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))),
- (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))));
+ getFilter(self)->setColor((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
// success
return 0;
}
@@ -108,15 +108,15 @@ static int setLimits (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set limits
- getFilter(self)->setLimits((unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
- (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))));
+ getFilter(self)->setLimits((unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+ (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))));
// success
return 0;
}
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index eb86f520e02..5ff1f7f11ce 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -147,10 +147,10 @@ static int setMatrix (PyFilter * self, PyObject * value, void * closure)
for (int c = 0; valid && c < 5; ++c)
{
// item must be int
- valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c));
+ valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
// if it is valid, save it in matrix
if (valid)
- mat[r][c] = short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c)));
+ mat[r][c] = short(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
}
}
// if parameter is not valid, report error
@@ -286,10 +286,10 @@ static int setLevels (PyFilter * self, PyObject * value, void * closure)
for (int c = 0; valid && c < 2; ++c)
{
// item must be int
- valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c));
+ valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
// if it is valid, save it in matrix
if (valid)
- lev[r][c] = (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c)));
+ lev[r][c] = (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
}
}
// if parameter is not valid, report error
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
index 002be6c3189..9a2b1e90d5a 100644
--- a/source/gameengine/VideoTexture/FilterNormal.cpp
+++ b/source/gameengine/VideoTexture/FilterNormal.cpp
@@ -72,13 +72,13 @@ static PyObject * getColor (PyFilter * self, void * closure)
static int setColor (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
- if (value == NULL || !PyLong_Check(value))
+ if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "filt.colorIdx = int: VideoTexture.FilterNormal, expected the value must be a int");
return -1;
}
// set color index
- getFilter(self)->setColor((unsigned short)(PyLong_AsSsize_t(value)));
+ getFilter(self)->setColor((unsigned short)(PyInt_AsLong(value)));
// success
return 0;
}
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index d8be08e0eb5..c4fb1fefd9c 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -331,19 +331,19 @@ static int setBackground (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 4
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 3)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255");
return -1;
}
// set background color
- getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
- (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))),
- (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))),
- (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3))));
+ getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 3))));
// success
return 0;
}
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index 55b14396280..d2c23e758f6 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -218,16 +218,16 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set position
GLint pos [] = {
- GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
- GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))
+ GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+ GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))
};
getImageViewport(self)->setPosition(pos);
// success
@@ -246,16 +246,16 @@ int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closu
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set capture size
short size [] = {
- short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
- short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))
+ short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+ short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))
};
getImageViewport(self)->setCaptureSize(size);
// success
diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp
index 5de7a9e80a9..5d449a158d8 100644
--- a/source/gameengine/VideoTexture/VideoBase.cpp
+++ b/source/gameengine/VideoTexture/VideoBase.cpp
@@ -167,13 +167,13 @@ PyObject * Video_getRepeat (PyImage * self, void * closure)
int Video_setRepeat (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
- if (value == NULL || !PyLong_Check(value))
+ if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be an int");
return -1;
}
// set repeat
- getVideo(self)->setRepeat(int(PyLong_AsSsize_t(value)));
+ getVideo(self)->setRepeat(int(PyInt_AsLong(value)));
// success
return 0;
}
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index cf4ea88c1b5..1a5481488c0 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -1095,13 +1095,13 @@ PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
- if (value == NULL || !PyLong_Check(value))
+ if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be an integer");
return -1;
}
// set preseek
- getFFmpeg(self)->setPreseek(PyLong_AsSsize_t(value));
+ getFFmpeg(self)->setPreseek(PyInt_AsLong(value));
// success
return 0;
}
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index 22171f69321..dad52a426b6 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -67,7 +67,7 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args)
// get last error description
static PyObject * getLastError (PyObject *self, PyObject *args)
{
- return PyUnicode_FromString(Exception::m_lastError.c_str());
+ return PyString_FromString(Exception::m_lastError.c_str());
}
// set log file
diff --git a/source/nan_compile.mk b/source/nan_compile.mk
index bc264fe5c1d..bd6dd6e1baa 100644
--- a/source/nan_compile.mk
+++ b/source/nan_compile.mk
@@ -71,6 +71,21 @@ DBG_CCFLAGS += -g
# OS dependent parts ---------------------------------------------------
+ifeq ($(OS),beos)
+ CC = gcc
+ CCC = g++
+ CFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing
+ CCFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing
+ REL_CFLAGS += -O2
+ REL_CCFLAGS += -O2
+ NAN_DEPEND = true
+ OPENGL_HEADERS = .
+ CPPFLAGS += -D__BeOS
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
ifeq ($(OS),darwin)
CC = gcc
CCC = g++
diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk
index 91f90525c1e..b9e623ed4e4 100644
--- a/source/nan_definitions.mk
+++ b/source/nan_definitions.mk
@@ -91,6 +91,7 @@ endif
export BF_PROFILE ?= false
export NAN_USE_BULLET ?= true
export NAN_BULLET2 ?= $(LCGDIR)/bullet2
+ export NAN_SUMO ?= $(SRCHOME)/gameengine/Physics/Sumo
export NAN_FUZZICS ?= $(SRCHOME)/gameengine/Physics/Sumo/Fuzzics
export NAN_BLENKEY ?= $(LCGDIR)/blenkey
export NAN_DECIMATION ?= $(LCGDIR)/decimation
@@ -130,6 +131,45 @@ endif
endif
# Platform Dependent settings go below:
+ ifeq ($(OS),beos)
+
+ export ID = $(USER)
+ export HOST = $(HOSTNAME)
+ export NAN_PYTHON ?= $(LCGDIR)/python
+ export NAN_PYTHON_VERSION ?= 2.3
+ export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION)
+ export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ export NAN_OPENAL ?= $(LCGDIR)/openal
+ export NAN_JPEG ?= $(LCGDIR)/jpeg
+ export NAN_PNG ?= $(LCGDIR)/png
+ export NAN_TIFF ?= $(LCGDIR)/tiff
+ export NAN_ODE ?= $(LCGDIR)/ode
+ export NAN_TERRAPLAY ?= $(LCGDIR)/terraplay
+ export NAN_MESA ?= /usr/src/Mesa-3.1
+ export NAN_ZLIB ?= $(LCGDIR)/zlib
+ export NAN_NSPR ?= $(LCGDIR)/nspr
+ export NAN_FREETYPE ?= $(LCGDIR)/freetype
+ export NAN_GETTEXT ?= $(LCGDIR)/gettext
+ export NAN_SDL ?= $(shell sdl-config --prefix)
+ export NAN_SDLLIBS ?= $(shell sdl-config --libs)
+ export NAN_SDLCFLAGS ?= $(shell sdl-config --cflags)
+
+ # Uncomment the following line to use Mozilla inplace of netscape
+ # CPPFLAGS +=-DMOZ_NOT_NET
+ # Location of MOZILLA/Netscape header files...
+ export NAN_MOZILLA_INC ?= $(LCGDIR)/mozilla/include
+ export NAN_MOZILLA_LIB ?= $(LCGDIR)/mozilla/lib/
+ # Will fall back to look in NAN_MOZILLA_INC/nspr and NAN_MOZILLA_LIB
+ # if this is not set.
+
+ export NAN_BUILDINFO ?= true
+ # Be paranoid regarding library creation (do not update archives)
+ export NAN_PARANOID ?= true
+
+ # l10n
+ #export INTERNATIONAL ?= true
+
+ else
ifeq ($(OS),darwin)
export ID = $(shell whoami)
@@ -549,6 +589,7 @@ endif
endif # irix
endif # freebsd
endif # darwin
+ endif # beos
endif # CONFIG_GUESS
diff --git a/source/nan_link.mk b/source/nan_link.mk
index 63c9a578498..42b17b425b3 100644
--- a/source/nan_link.mk
+++ b/source/nan_link.mk
@@ -49,6 +49,10 @@ endif
# default (overriden by windows)
SOEXT = .so
+ifeq ($(OS),beos)
+ LLIBS = -L/boot/develop/lib/x86/ -lGL -lbe -L/boot/home/config/lib/
+endif
+
ifeq ($(OS),darwin)
LLIBS += -lGLU -lGL
LLIBS += -lz -lstdc++
diff --git a/tools/btools.py b/tools/btools.py
index 9603022deaa..377a389941f 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -44,8 +44,9 @@ def validate_arguments(args, bc):
'WITH_BF_INTERNATIONAL',
'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'BF_GETTEXT_LIBPATH',
'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH',
- 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB',
- 'BF_WINTAB', 'BF_WINTAB_INC',
+ 'WITH_BF_ODE', 'BF_ODE', 'BF_ODE_INC', 'BF_ODE_LIB',
+ 'WITH_BF_GAMEENGINE', 'WITH_BF_SOLID', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB',
+ 'BF_SOLID', 'BF_SOLID_INC', 'BF_WINTAB', 'BF_WINTAB_INC',
'WITH_BF_FREETYPE', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH',
'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH',
'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC',
@@ -250,11 +251,19 @@ def read_opts(cfg, args):
(BoolVariable('WITH_BF_GAMEENGINE', 'Build with gameengine' , False)),
+ (BoolVariable('WITH_BF_ODE', 'Use ODE if true', True)),
+ ('BF_ODE', 'ODE base path', ''),
+ ('BF_ODE_INC', 'ODE include path' , ''),
+ ('BF_ODE_LIB', 'ODE library', ''),
+
(BoolVariable('WITH_BF_BULLET', 'Use Bullet if true', True)),
('BF_BULLET', 'Bullet base dir', ''),
('BF_BULLET_INC', 'Bullet include path', ''),
('BF_BULLET_LIB', 'Bullet library', ''),
+ (BoolVariable('WITH_BF_SOLID', 'Use Sumo/Solid deprecated physics system if true', True)),
+ ('BF_SOLID', 'Solid base dir', '#/extern/solid'),
+ ('BF_SOLID_INC', 'Solid include path', ''),
('BF_WINTAB', 'WinTab base dir', ''),
('BF_WINTAB_INC', 'WinTab include dir', ''),
('BF_CXX', 'c++ base path for libstdc++, only used when static linking', ''),