Merge from Harmonic Skeleton branch
authorMartin Poirier <theeth@yahoo.com>
Mon, 10 Dec 2007 21:14:19 +0000 (21:14 +0000)
committerMartin Poirier <theeth@yahoo.com>
Mon, 10 Dec 2007 21:14:19 +0000 (21:14 +0000)
This code adds a basic and simple skeleton generator.

Examples and links are in the wiki, docs will come eventually: http://wiki.blender.org/index.php/User:Theeth/skeletor

In a nutshell, select a vertex at the top of the head and press "Generate Skeleton". UI Panel is in the Editing buttons in Edit Mode, tooltips and semi-useful.

304 files changed:
extern/bFTGL/include/FTGL.h
extern/bFTGL/src/Makefile
intern/elbeem/extern/elbeem.h
intern/elbeem/intern/attributes.cpp
intern/elbeem/intern/isosurface.cpp
intern/elbeem/intern/loop_tools.h
intern/elbeem/intern/ntl_vector3dim.h
intern/elbeem/intern/paraloopend.h [new file with mode: 0644]
intern/elbeem/intern/particletracer.cpp
intern/elbeem/intern/simulation_object.cpp
intern/elbeem/intern/solver_adap.cpp
intern/elbeem/intern/solver_class.h
intern/elbeem/intern/solver_init.cpp
intern/elbeem/intern/solver_interface.cpp
intern/elbeem/intern/solver_interface.h
intern/elbeem/intern/solver_main.cpp
intern/elbeem/intern/solver_util.cpp
intern/elbeem/intern/utilities.cpp
intern/elbeem/intern/utilities.h
intern/ghost/intern/GHOST_SystemWin32.cpp
intern/iksolver/intern/IK_QSegment.cpp
intern/opennl/intern/opennl.c
po/Makefile
projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj
projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj
projectfiles_vc7/blender/imbuf/BL_imbuf.vcproj
projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
projectfiles_vc7/blender/render/BRE_render.vcproj
projectfiles_vc7/blender/src/BL_src.vcproj
release/Makefile
release/datafiles/blenderbuttons
release/datafiles/preview.blend
release/scripts/bpymodules/BPyMessages.py
release/scripts/flt_defaultp.py [new file with mode: 0644]
release/scripts/flt_export.py
release/scripts/flt_filewalker.py
release/scripts/flt_import.py
release/scripts/flt_palettemanager.py [new file with mode: 0644]
release/scripts/flt_properties.py [new file with mode: 0644]
release/scripts/flt_toolbar.py [new file with mode: 0644]
release/scripts/import_dxf.py
release/scripts/mesh_edges2curves.py
release/scripts/mesh_skin.py
release/scripts/mesh_wire.py
release/scripts/ply_export.py
release/scripts/reeb.py [deleted file]
release/scripts/weightpaint_average.py
release/scripts/weightpaint_invert.py [new file with mode: 0644]
release/scripts/weightpaint_normalize.py
release/scripts/wizard_curve2tree.py [new file with mode: 0644]
source/Makefile
source/blender/Makefile
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_displist.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_lattice.h
source/blender/blenkernel/BKE_main.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_particle.h [new file with mode: 0644]
source/blender/blenkernel/BKE_pointcache.h [new file with mode: 0644]
source/blender/blenkernel/BKE_softbody.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c [new file with mode: 0644]
source/blender/blenkernel/intern/particle_system.c [new file with mode: 0644]
source/blender/blenkernel/intern/pointcache.c [new file with mode: 0644]
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_fnmatch.h [new file with mode: 0644]
source/blender/blenlib/BLI_kdtree.h [new file with mode: 0644]
source/blender/blenlib/BLI_rand.h
source/blender/blenlib/intern/BLI_kdtree.c [new file with mode: 0644]
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/fnmatch.c [new file with mode: 0644]
source/blender/blenlib/intern/rand.c
source/blender/blenlib/intern/threads.c
source/blender/blenlib/intern/util.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/ftfont/intern/Makefile
source/blender/include/BDR_editcurve.h
source/blender/include/BDR_editobject.h
source/blender/include/BIF_butspace.h
source/blender/include/BIF_editaction.h
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_editdeform.h
source/blender/include/BIF_editparticle.h [new file with mode: 0644]
source/blender/include/BIF_editseq.h
source/blender/include/BIF_editsima.h
source/blender/include/BIF_editview.h
source/blender/include/BIF_filelist.h
source/blender/include/BIF_gl.h
source/blender/include/BIF_meshtools.h
source/blender/include/BIF_poseobject.h
source/blender/include/BIF_resources.h
source/blender/include/BIF_transform.h
source/blender/include/BIF_usiblender.h
source/blender/include/BSE_drawview.h
source/blender/include/BSE_edit.h
source/blender/include/BSE_editipo.h
source/blender/include/BSE_sequence.h
source/blender/include/blendef.h
source/blender/include/butspace.h
source/blender/include/transform.h
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_customdata_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_key_types.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_nla_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_particle_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c
source/blender/nodes/intern/CMP_nodes/CMP_glare.c
source/blender/nodes/intern/CMP_nodes/CMP_scale.c
source/blender/nodes/intern/CMP_nodes/CMP_texture.c
source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
source/blender/nodes/intern/CMP_nodes/Makefile
source/blender/nodes/intern/Makefile
source/blender/nodes/intern/SHD_nodes/Makefile
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Constraint.c
source/blender/python/api2_2x/CurNurb.c
source/blender/python/api2_2x/Curve.c
source/blender/python/api2_2x/Geometry.c
source/blender/python/api2_2x/Lamp.c
source/blender/python/api2_2x/Mesh.c
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/Scene.c
source/blender/python/api2_2x/Texture.c
source/blender/python/api2_2x/Window.c
source/blender/python/api2_2x/doc/Blender.py
source/blender/python/api2_2x/doc/Curve.py
source/blender/python/api2_2x/doc/Mesh.py
source/blender/python/api2_2x/doc/Object.py
source/blender/python/api2_2x/doc/Render.py
source/blender/python/api2_2x/doc/Text3d.py
source/blender/python/api2_2x/doc/Texture.py
source/blender/python/api2_2x/doc/Window.py
source/blender/python/api2_2x/sceneRender.c
source/blender/python/api2_2x/sceneSequence.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/extern/include/RE_raytrace.h
source/blender/render/extern/include/RE_render_ext.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/renderdatabase.h
source/blender/render/intern/include/shading.h
source/blender/render/intern/include/strand.h [new file with mode: 0644]
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/raytrace.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadbuf.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/strand.c [new file with mode: 0644]
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/zbuf.c
source/blender/src/SConscript
source/blender/src/blenderbuttons.c
source/blender/src/butspace.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/buttons_scene.c
source/blender/src/buttons_shading.c
source/blender/src/drawaction.c
source/blender/src/drawarmature.c
source/blender/src/drawimage.c
source/blender/src/drawipo.c
source/blender/src/drawmesh.c
source/blender/src/drawnla.c
source/blender/src/drawnode.c
source/blender/src/drawobject.c
source/blender/src/drawscene.c
source/blender/src/drawseq.c
source/blender/src/drawsound.c
source/blender/src/drawtext.c
source/blender/src/drawtime.c
source/blender/src/drawview.c
source/blender/src/edit.c
source/blender/src/editaction.c
source/blender/src/editarmature.c
source/blender/src/editcurve.c
source/blender/src/editdeform.c
source/blender/src/editface.c
source/blender/src/editimasel.c
source/blender/src/editipo.c
source/blender/src/editipo_lib.c
source/blender/src/editipo_mods.c
source/blender/src/editkey.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_lib.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editnla.c
source/blender/src/editobject.c
source/blender/src/editparticle.c [new file with mode: 0644]
source/blender/src/editscreen.c
source/blender/src/editseq.c
source/blender/src/editsima.c
source/blender/src/editview.c
source/blender/src/filelist.c
source/blender/src/filesel.c
source/blender/src/header_action.c
source/blender/src/header_buttonswin.c
source/blender/src/header_info.c
source/blender/src/header_ipo.c
source/blender/src/header_nla.c
source/blender/src/header_node.c
source/blender/src/header_seq.c
source/blender/src/header_view3d.c
source/blender/src/headerbuttons.c
source/blender/src/interface.c
source/blender/src/interface_panel.c
source/blender/src/meshlaplacian.c
source/blender/src/meshtools.c
source/blender/src/outliner.c
source/blender/src/parametrizer.c
source/blender/src/playanim.c
source/blender/src/poseobject.c
source/blender/src/preview.blend.c
source/blender/src/renderwin.c
source/blender/src/resources.c
source/blender/src/sculptmode.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/toets.c
source/blender/src/transform.c
source/blender/src/transform_constraints.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/transform_manipulator.c
source/blender/src/unwrapper.c
source/blender/src/usiblender.c
source/blender/src/view.c
source/blender/src/vpaint.c
source/blender/src/writeimage.c
source/creator/buildinfo.c
source/creator/creator.c
source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
source/gameengine/Converter/BL_SkinDeformer.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/Ketsji/BL_Shader.cpp
source/gameengine/Ketsji/BL_Texture.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/nan_compile.mk
source/nan_definitions.mk
source/nan_link.mk
tools/Blender.py
tools/btools.py

index e92bd5260125a275386b4898852c122b79ad6c4f..2b76de8b8bdddf527e366d19f2131b36443bf3d3 100644 (file)
@@ -42,7 +42,11 @@ typedef float    FTGL_FLOAT;
             #include <OpenGL/glu.h>
         #else
             #include <GL/gl.h>
-            #include <GL/glu.h>
+            #if defined (__sun__) && !defined (__sparc__)
+                #include <mesa/glu.h>
+            #else
+                #include <GL/glu.h>
+            #endif
         #endif                
 
     #endif
index 064480fbd16be74bf9a02e4c30e8cbdbc1501341..3ebf9bee45ced8e9aa268696e84852c990508e8d 100644 (file)
@@ -46,7 +46,8 @@ CCSRCS =  FTBitmapGlyph.cpp FTCharmap.cpp FTContour.cpp FTExtrdGlyph.cpp \
 
 include nan_compile.mk 
 CPPFLAGS += -I../include
-CPPFLAGS += -I$(NAN_FREETYPE)/include -I$(NAN_FREETYPE)/include/freetype2 
+CPPFLAGS += -I$(NAN_FREETYPE)/include -I$(NAN_FREETYPE)/include/freetype2
+CPPFLAGS += -I$(OPENGL_HEADERS) 
 
 install: all debug
        @[ -d $(NAN_FTGL) ] || mkdir -p $(NAN_FTGL)
index b3feda8bbe8be0dee4385b1112080fdda6875707..2a594dd07e65147fd443513bba72b9207009f0ad 100644 (file)
@@ -154,7 +154,7 @@ typedef struct elbeemMesh {
        short volumeInitType;
 
        /* name of the mesh, mostly for debugging */
-       char *name;
+       const char *name;
 } elbeemMesh;
 
 // API functions
index 8e337a92a4e61648629372332d84d488b4b3e4f2..464486f2500ea1b995de7bfcc940d7838d1fa0ac 100644 (file)
@@ -103,7 +103,7 @@ void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string sou
 
 // set that a parameter can be given, and will be ignored...
 bool AttributeList::ignoreParameter(string name, string source) {
-       name=source=(""); // remove warning
+       name = source = ("");
        return false;
 }
                
index 9925565b85d67f55fd6785d172db95ad5b33db9b..f6b3e08527af20018852606ca3ed8e7b5efa498b 100644 (file)
 #include <algorithm>
 #include <stdio.h>
 
+#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
+#include <ieeefp.h>
+#endif
+
+
 // just use default rounding for platforms where its not available
 #ifndef round
 #define round(x) (x)
index 3c15a6092103ad1ec2f65a61f720b40d16441264..70ecb9ce3e080cec9fc77b4f042b607d050e6c7e 100644 (file)
 
 
        
-#define unused_GRID_REGION_END() \
-       } /* main_region */  \
-       // end unusedGRID_REGION_END
-
 
 //  -----------------------------------------------------------------------------------
 #else // PARALLEL==1
 
-#include "paraloop.h"
+//#include "paraloop.h"
+#define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, calcMaxVlen, calcMxvx,calcMxvy,calcMxvz);
+#define LIST_EMPTY(x)    calcListEmpty.push_back( x );
+#define LIST_FULL(x)     calcListFull.push_back( x );
+#define FSGR_ADDPART(x)  calcListParts.push_back( x );
+
+
+// parallel region
+//was: # pragma omp parallel default(shared) 
+#if COMPRESSGRIDS!=1
+       // requires compressed grids...!
+       ERROR!
+#endif
+
+// loop start
+#define  GRID_REGION_START()  \
+       { \
+        \
+        \
+       if(mSizez<2) { \
+       mPanic = 1; \
+       errFatal("ParaLoop::2D","Not valid...!", SIMWORLD_GENERICERROR); \
+       } \
+        \
+        \
+       vector<LbmPoint> calcListFull; \
+       vector<LbmPoint> calcListEmpty; \
+       vector<ParticleObject> calcListParts; \
+       LbmFloat calcMxvx, calcMxvy, calcMxvz, calcMaxVlen; \
+       calcMxvx = calcMxvy = calcMxvz = calcMaxVlen = 0.0; \
+       calcListEmpty.reserve(mListEmpty.capacity() / omp_get_num_threads() ); \
+       calcListFull.reserve( mListFull.capacity()  / omp_get_num_threads() ); \
+       calcListParts.reserve(mSizex); \
+        \
+        \
+       const int id = omp_get_thread_num(); \
+       const int Nthrds = omp_get_num_threads(); \
+        \
+        \
+        \
+        \
+        \
+       int kdir = 1; \
+        \
+       int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \
+       if(gridLoopBound>0){ kstart=getForZMin1(); kend=getForZMax1(mMaxRefine); } \
+       LbmFloat *ccel = NULL, *tcel = NULL; \
+       CellFlagType *pFlagSrc=NULL, *pFlagDst=NULL; \
+        \
+        \
+       if(mLevel[mMaxRefine].setCurr==1) { \
+       kdir = -1; \
+       int temp = kend; \
+       kend = kstart-1; \
+       kstart = temp-1; \
+       } \
+        \
+       const int Nj = mLevel[mMaxRefine].lSizey; \
+       int jstart = 0+( id * (Nj / Nthrds) ); \
+       int jend   = 0+( (id+1) * (Nj / Nthrds) ); \
+       if( ((Nj/Nthrds) *Nthrds) != Nj) { \
+       errMsg("LbmFsgrSolver","Invalid domain size Nj="<<Nj<<" Nthrds="<<Nthrds); \
+       } \
+        \
+       if(jstart<gridLoopBound) jstart = gridLoopBound; \
+       if(jend>mLevel[mMaxRefine].lSizey-gridLoopBound) jend = mLevel[mMaxRefine].lSizey-gridLoopBound; \
+        \
+       debMsgStd("ParaLoop::OMP",DM_MSG,"Thread:"<<id<<" i:"<<istart<<"-"<<iend<<" j:"<<jstart<<"-"<<jend<<", k:"<<kstart<<"-"<<kend<<"  ", 1); \
+        \
+
+
+
+
+// para GRID LOOP END is parainc3 
 
 #endif // PARALLEL==1
 
 
 
 
+
 // old loop for COMPRESSGRIDS==0
 #define old__GRID_LOOP_START() \
   for(int k=kstart;k<kend;++k) { \
          for(int j=1;j<mLevel[lev].lSizey-1;++j) { \
                for(int i=0;i<mLevel[lev].lSizex-2;   ) {
 
+
index 912a37350c127f2b0c984787a60ea2663b4d660e..27c3be0d71f143758b8e8ec3e1f53738bd115a31 100644 (file)
@@ -22,6 +22,7 @@
 #include <math.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 // hack for MSVC6.0 compiler
 #ifdef _MSC_VER
diff --git a/intern/elbeem/intern/paraloopend.h b/intern/elbeem/intern/paraloopend.h
new file mode 100644 (file)
index 0000000..6bb224b
--- /dev/null
@@ -0,0 +1,42 @@
+
+// same as grid loop_end + barrier
+
+                       } // i
+               int i=0; //dummy
+               ADVANCE_POINTERS(2*gridLoopBound);
+       } // j
+
+#      if COMPRESSGRIDS==1
+#      if PARALLEL==1
+       //frintf(stderr," (id=%d k=%d) ",id,k);
+#pragma omp barrier
+#      endif // PARALLEL==1
+#      else // COMPRESSGRIDS==1
+       int i=0; //dummy
+       ADVANCE_POINTERS(mLevel[lev].lSizex*2);
+#      endif // COMPRESSGRIDS==1
+
+} // all cell loop k,j,i
+
+#pragma omp critical
+{
+       if(doReduce) {
+               // synchronize global vars
+               for(int j=0; j<calcListFull.size() ; j++) mListFull.push_back( calcListFull[j] ); 
+               for(int j=0; j<calcListEmpty.size(); j++) mListEmpty.push_back( calcListEmpty[j] ); 
+               for(int j=0; j<calcListParts.size(); j++) mpParticles->addFullParticle( calcListParts[j] );
+               if(calcMaxVlen>mMaxVlen) {  
+                       mMxvx = calcMxvx;  
+                       mMxvy = calcMxvy;  
+                       mMxvz = calcMxvz;  
+                       mMaxVlen = calcMaxVlen;  
+               }  
+               if(0) {debMsgStd("OMP_CRIT",DM_MSG,     "reduce id"<<id<<" curr: "<<mMaxVlen<<"|"<<mMxvx<<","<<mMxvy<<","<<mMxvz<< 
+                                                                                                                                                               "      calc[ "<<calcMaxVlen<<"|"<<calcMxvx<<","<<calcMxvy<<","<<calcMxvz<<"]  " ,4 ); }
+       }
+} // critical
+
+
+} /* main_region */  
+       //?lobOutstrForce = true;
+
index c9da808543a0a9f8acc77430a9c71e43fa1f31f2..819fcdd0b9aacd25b868276bd5a43f5094decde9 100644 (file)
@@ -325,7 +325,7 @@ void ParticleTracer::getTriangles(double time, vector<ntlTriangle> *triangles,
        // suppress warnings...
        vertices = NULL; triangles = NULL;
        normals = NULL; objectId = 0;
-       time = 0.0;
+       time = 0.;
 #else // ELBEEM_PLUGIN
        int pcnt = 0;
        // currently not used in blender
index 2ff600a36d4ee07324db1acfa997da8059371b48..9b47ae696afff4a2d784e0a00f23406d59034da1 100644 (file)
@@ -15,7 +15,6 @@
 #include "solver_interface.h"
 #include "particletracer.h"
 #include "elbeem.h"
-#include <stdlib.h> /* exit(3) - also in linux */
 
 #ifdef _WIN32
 #else
@@ -69,6 +68,7 @@ SimulationObject::~SimulationObject()
 /*! init tree for certain geometry init */
 /*****************************************************************************/
 void SimulationObject::initGeoTree() {
+       // unused!! overriden by solver interface       
        if(mpGlob == NULL) { 
                errFatal("SimulationObject::initGeoTree error","Requires globals!", SIMWORLD_INITERROR); 
                return;
@@ -80,7 +80,7 @@ void SimulationObject::initGeoTree() {
        char treeFlag = (1<<(mGeoInitId+4));
        mpGiTree = new ntlTree( 20, 4, // warning - fixed values for depth & maxtriangles here...
                                                                                                scene, treeFlag );
-       exit(1); // unused!? overriden by solver interface      
+       // unused!! overriden by solver interface       
 }
 
 /*****************************************************************************/
@@ -310,7 +310,7 @@ void SimulationObject::step( void )
                // dont advance for stopped time
                mpLbm->step();
                mTime += mpParam->getTimestep();
-//if(mTime>0.001) { errMsg("DEBUG!!!!!!!!","quit mlsu..."); exit(1); } // PROFILE DEBUG TEST!
+               //if(mTime>0.001) { errMsg("DEBUG!!!!!!!!","quit mlsu..."); xit(1); } // PROFILE DEBUG TEST!
        }
        if(mpLbm->getPanic()) mPanic = true;
 
index ef516a578bd1a5741d1b273b6f5a0f1bd55420de..b56b1c14f2cc9f85724e61daa80ee7a6d4db1247 100644 (file)
@@ -11,6 +11,9 @@
 #include "solver_relax.h"
 #include "particletracer.h"
 
+#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
+#include <ieeefp.h>
+#endif
 
 
 /*****************************************************************************/
index 930c1863aa7bce2948be79753fa38a0bb22ddb0a..d46f065adfd6632ed9aa4b58479ce0a510b42c1a 100644 (file)
 // sirdude fix for solaris
 #if !defined(linux) && defined(sun)
 #ifndef expf
-#define expf(a)                exp((double)(a))
+#define expf(x) exp((double)(x))
 #endif
 #endif
 
index abec4a89c89b1f4abb726769c77caa29f3bee58c..c953d2f47da66979878b645e62bfc1f28aec0679 100644 (file)
@@ -655,6 +655,7 @@ bool LbmFsgrSolver::initializeSolverMemory()
        int orgSz = mSizez;
        double sizeReduction = 1.0;
        double memEstFromFunc = -1.0;
+       double memEstFine = -1.0;
        string memreqStr("");   
        bool firstMInit = true;
        int minitTries=0;
@@ -672,7 +673,7 @@ bool LbmFsgrSolver::initializeSolverMemory()
                firstMInit=false;
 
                calculateMemreqEstimate( mSizex, mSizey, mSizez, 
-                               mMaxRefine, mFarFieldSize, &memEstFromFunc, &memreqStr );
+                               mMaxRefine, mFarFieldSize, &memEstFromFunc, &memEstFine, &memreqStr );
                
                double memLimit;
                string memLimStr("-");
@@ -685,13 +686,36 @@ bool LbmFsgrSolver::initializeSolverMemory()
                        memLimit = 16.0* 1024.0*1024.0*1024.0;
                        memLimStr = string("16GB");
                }
-               if(memEstFromFunc>memLimit) {
+
+               // restrict max. chunk of 1 mem block to 1GB for windos
+               bool memBlockAllocProblem = false;
+               double maxWinMemChunk = 1100.*1024.*1024.;
+               double maxMacMemChunk = 1200.*1024.*1024.;
+               double maxDefaultMemChunk = 2.*1024.*1024.*1024.;
+               //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG
+#ifdef WIN32
+               if(memEstFine> maxWinMemChunk) {
+                       memBlockAllocProblem = true;
+               }
+#endif // WIN32
+#ifdef __APPLE__
+               if(memEstFine> maxMacMemChunk) {
+                       memBlockAllocProblem = true;
+               }
+#endif // Mac
+               if(sizeof(void *)==4 && memEstFine>maxDefaultMemChunk) {
+                       // max memory chunk for 32bit systems 2gig
+                       memBlockAllocProblem = true;
+               }
+
+               if(memEstFromFunc>memLimit || memBlockAllocProblem) {
                        sizeReduction *= 0.9;
                        mSizex = (int)(orgSx * sizeReduction);
                        mSizey = (int)(orgSy * sizeReduction);
                        mSizez = (int)(orgSz * sizeReduction);
                        debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<
                                        //memEstFromFunc<<"/"<<memLimit<<", "<<
+                                       //memEstFine<<"/"<<maxWinMemChunk<<", "<<
                                        memreqStr<<"/"<<memLimStr<<", "<<
                                        "retrying: "<<PRINT_VEC(mSizex,mSizey,mSizez)<<" org:"<<PRINT_VEC(orgSx,orgSy,orgSz)
                                        , 3 );
@@ -778,10 +802,6 @@ bool LbmFsgrSolver::initializeSolverMemory()
        mLevel[ mMaxRefine ].simCellSize = mpParam->getCellSize();
        mLevel[ mMaxRefine ].lcellfactor = 1.0;
        LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum);
-       // +4 for safety ?
-       mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
-       mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
-       ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
 
 #if COMPRESSGRIDS==0
        mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ];
@@ -789,11 +809,34 @@ bool LbmFsgrSolver::initializeSolverMemory()
        ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
 #else // COMPRESSGRIDS==0
        LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2);
+       // D int tmp = ( (rcellSize +compressOffset +4)/(1024*1024) )*4;
+       // D printf("Debug MEMMMM excee: %d\n", tmp);
        mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ];
        mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset;
        ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4);
 #endif // COMPRESSGRIDS==0
 
+       if(!mLevel[ mMaxRefine ].mprsCells[1] || !mLevel[ mMaxRefine ].mprsCells[0]) {
+               errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (1)! Aborting...",SIMWORLD_INITERROR);
+               return false;
+       }
+
+       // +4 for safety ?
+       mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
+       mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
+       ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
+       if(!mLevel[ mMaxRefine ].mprsFlags[1] || !mLevel[ mMaxRefine ].mprsFlags[0]) {
+               errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (2)! Aborting...",SIMWORLD_INITERROR);
+
+#if COMPRESSGRIDS==0
+               delete[] mLevel[ mMaxRefine ].mprsCells[0];
+               delete[] mLevel[ mMaxRefine ].mprsCells[1];
+#else // COMPRESSGRIDS==0
+               delete[] mLevel[ mMaxRefine ].mprsCells[1];
+#endif // COMPRESSGRIDS==0
+               return false;
+       }
+
        LbmFloat lcfdimFac = 8.0;
        if(LBMDIM==2) lcfdimFac = 4.0;
        for(int i=mMaxRefine-1; i>=0; i--) {
index 2539556617bb4752e6d81b4f07e4c3e4ba92ad25..d25850a003be81de8a3894110a15b789a8c55070 100644 (file)
@@ -17,7 +17,6 @@
 #include "ntl_world.h"
 #include "elbeem.h"
 
-#include <stdlib.h> /* getenv(3) - also in linux */
 
 
 
@@ -142,7 +141,7 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
 
 void calculateMemreqEstimate( int resx,int resy,int resz, 
                int refine, float farfield,
-               double *reqret, string *reqstr) {
+               double *reqret, double *reqretFine, string *reqstr) {
        // debug estimation?
        const bool debugMemEst = true;
        // COMPRESSGRIDS define is not available here, make sure it matches
@@ -150,6 +149,7 @@ void calculateMemreqEstimate( int resx,int resy,int resz,
        // make sure we can handle bid numbers here... all double
        double memCnt = 0.0;
        double ddTotalNum = (double)dTotalNum;
+       if(reqretFine) *reqretFine = -1.;
 
        double currResx = (double)resx;
        double currResy = (double)resy;
@@ -159,10 +159,12 @@ void calculateMemreqEstimate( int resx,int resy,int resz,
        if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"res:"<<PRINT_VEC(currResx,currResy,currResz)<<" rcellSize:"<<rcellSize<<" mc:"<<memCnt, 10);
   if(!useGridComp) {
                memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0);
+               if(reqretFine) *reqretFine = (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0);
                if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," no-comp, mc:"<<memCnt, 10);
        } else {
                double compressOffset = (double)(currResx*currResy*ddTotalNum*2.0);
                memCnt += (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0));
+               if(reqretFine) *reqretFine = (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0));
                if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," w-comp, mc:"<<memCnt, 10);
        }
        for(int i=refine-1; i>=0; i--) {
index 1dfdf156ee50b6d28436694f4d52d038c0d4cbeb..c3dc4983cac33c221b7fb160e59b9731834918a0 100644 (file)
@@ -21,7 +21,7 @@
 #if LBM_USE_GUI==1
 #define USE_GLUTILITIES
 // for debug display
-#include <GL/gl.h>
+//#include <GL/gl.h>
 #include "../gui/guifuncs.h"
 #endif
 
@@ -596,8 +596,10 @@ class LbmSolverInterface
 void initGridSizes(int &mSizex, int &mSizey, int &mSizez,
                ntlVec3Gfx &mvGeoStart, ntlVec3Gfx &mvGeoEnd, 
                int mMaxRefine, bool parallel);
+// return the amount of memory required in total (reqret)
+// and for the finest grid only (reqretFine, can be NULL)
 void calculateMemreqEstimate(int resx,int resy,int resz, int refine,
-               float farfieldsize, double *reqret, string *reqstr);
+               float farfieldsize, double *reqret, double *reqretFine, string *reqstr);
 
 //! helper function to convert flag to string (for debuggin)
 string convertCellFlagType2String( CellFlagType flag );
index 270e8867b3cea2a6e7f4986143cb7bd407ea8bb9..17163733fe9d2e3620aa5c399ad6817e14ea20e0 100644 (file)
@@ -7,11 +7,16 @@
  *
  *****************************************************************************/
 
-#include <stdlib.h> /* rand(3) - also in linux */
 #include "solver_class.h"
 #include "solver_relax.h"
 #include "particletracer.h"
 #include "loop_tools.h"
+#include <stdlib.h>
+
+#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
+#include <ieeefp.h>
+#endif
+
 
 /*****************************************************************************/
 /*! perform a single LBM step */
@@ -375,7 +380,11 @@ LbmFsgrSolver::mainLoop(int lev)
        const int gridLoopBound=1;
        GRID_REGION_INIT();
 #if PARALLEL==1
-#include "paraloopstart.h"
+#pragma omp parallel default(shared) \
+  reduction(+: \
+         calcCurrentMass,calcCurrentVolume, \
+               calcCellsFilled,calcCellsEmptied, \
+               calcNumUsedCells )
        GRID_REGION_START();
 #else // PARALLEL==1
        GRID_REGION_START();
@@ -1112,7 +1121,11 @@ LbmFsgrSolver::preinitGrids()
        
                GRID_REGION_INIT();
 #if PARALLEL==1
-#include "paraloopstart.h"
+#pragma omp parallel default(shared) \
+  reduction(+: \
+         calcCurrentMass,calcCurrentVolume, \
+               calcCellsFilled,calcCellsEmptied, \
+               calcNumUsedCells )
 #endif // PARALLEL==1
                GRID_REGION_START();
                GRID_LOOP_START();
@@ -1145,7 +1158,11 @@ LbmFsgrSolver::standingFluidPreinit()
 
        GRID_REGION_INIT();
 #if PARALLEL==1
-#include "paraloopstart.h"
+#pragma omp parallel default(shared) \
+  reduction(+: \
+         calcCurrentMass,calcCurrentVolume, \
+               calcCellsFilled,calcCellsEmptied, \
+               calcNumUsedCells )
 #endif // PARALLEL==1
        GRID_REGION_START();
 
index 65cc2200d4e624a436f41a596631e16defdbf167..a6685babe680b22aafc992d605b4c41b77846169 100644 (file)
@@ -15,8 +15,7 @@
 #include "ntl_world.h"
 #include "simulation_object.h"
 
-#include <stdlib.h> /* rand(3) */
-
+#include <stdlib.h>
 #include <zlib.h>
 #ifndef sqrtf
 #define sqrtf sqrt
index 332052e91b62ba3450dbc19d7c3f1a7429e77c98..551c4d0d3842769ee065de69df065cfd53988847 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <iostream>
 #include <sstream>
-#include <stdlib.h> /* getenv(3), strtol(3) */
 #ifdef WIN32
 // for timing
 #include <windows.h>
@@ -482,7 +481,7 @@ double elbeemEstimateMemreq(int res,
        double memreq = -1.0;
        string memreqStr("");   
        // ignore farfield for now...
-       calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, &memreqStr );
+       calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, NULL, &memreqStr );
 
        if(retstr) { 
                // copy at max. 32 characters
index 0f65408d23c7c0bd033a8437c60483909397c5ff..825e92251fe5d4d7705fb06b3878631ce3648730 100644 (file)
@@ -9,11 +9,6 @@
 #ifndef UTILITIES_H
 #include "ntl_vector3dim.h"
 
-// Solaris requires ieeefp.h for finite(3C)
-#if !defined(linux) && defined(sun)
-#include <ieeefp.h>
-#endif
-
 
 /* debugging outputs , debug level 0 (off) to 10 (max) */
 #ifdef ELBEEM_PLUGIN
index ec6d0d355b59977a22b786a088a5411c64fa4086..835f7da3038023ca72aa02761796398291afbd5c 100644 (file)
@@ -54,7 +54,7 @@
 #define WM_MOUSEWHEEL 0x020A
 #endif // WM_MOUSEWHEEL
 #ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120        /* Value for rolling one detent */
+#define WHEEL_DELTA 120        /* Value for rolling one detent, (old convention! MS changed it) */
 #endif // WHEEL_DELTA
 
 
@@ -479,7 +479,11 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP
 {
        // short fwKeys = LOWORD(wParam);                       // key flags
        int zDelta = (short) HIWORD(wParam);    // wheel rotation
-       zDelta /= WHEEL_DELTA;
+       
+       // zDelta /= WHEEL_DELTA;
+       // temporary fix below: microsoft now has added more precision, making the above division not work
+       if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
+       
        // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
        // short yPos = (short) HIWORD(lParam); // vertical position of pointer
        return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
index a5217ed91d63567d34153831d2ace421bd8444b3..bf38c369363222ef81cd1dc4668eef7de25721ee 100644 (file)
@@ -61,11 +61,11 @@ static MT_Scalar EulerAngleFromMatrix(const MT_Matrix3x3& R, int axis)
        MT_Scalar t = sqrt(R[0][0]*R[0][0] + R[0][1]*R[0][1]);
 
     if (t > 16.0*MT_EPSILON) {
-               if (axis == 0) return atan2(R[1][2], R[2][2]);
+               if (axis == 0) return -atan2(R[1][2], R[2][2]);
         else if(axis == 1) return atan2(-R[0][2], t);
-        else return atan2(R[0][1], R[0][0]);
+        else return -atan2(R[0][1], R[0][0]);
     } else {
-               if (axis == 0) return atan2(-R[2][1], R[1][1]);
+               if (axis == 0) return -atan2(-R[2][1], R[1][1]);
         else if(axis == 1) return atan2(-R[0][2], t);
         else return 0.0f;
     }
index 2d30da075d33979db1b62cf3e84809ac3e350dec..d779e861cb6947d7483704975b07c6132c0f0b0e 100644 (file)
@@ -240,7 +240,7 @@ static void __nlSparseMatrixConstruct(
        M->storage = storage;
        if(storage & __NL_ROWS) {
                M->row = __NL_NEW_ARRAY(__NLRowColumn, m);
-               for(i=0; i<n; i++) {
+               for(i=0; i<m; i++) {
                        __nlRowColumnConstruct(&(M->row[i]));
                }
        } else {
index b7288c0e64ce591a552393804f420e81dcab217a..35be6dd2a153f857fe2da65d64149231f182da1b 100644 (file)
@@ -36,7 +36,7 @@ SOURCEDIR = blender/po
 
 include nan_definitions.mk
 
-ifeq ($(INTERNTIONAL),true)
+ifeq ($(INTERNATIONAL),true)
        LINGUAS = ar bg ca cs de es fr hr it ja nl pl pt_BR ro ru sr sr@Latn sv uk zh_CN
 else
        LINGUAS = 
index 4e58c6617aac5ed6ea336adaef64edaaa0bf18db..15614f52fdf951910af3e852065cddedb3419708 100644 (file)
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
                                PreprocessorDefinitions="_DEBUG,WIN32,_LIB,WITH_FREETYPE2"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="1"
                        <Tool
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
                                PreprocessorDefinitions="NDEBUG,WIN32,_LIB,WITH_FREETYPE2,UNWRAPPER"
                                StringPooling="TRUE"
                                RuntimeLibrary="0"
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\packedFile.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\particle.c">
+                       </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\particle_system.c">
+                       </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\pointcache.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\property.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_packedFile.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\BKE_particle.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_plugin_types.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\BKE_pointcache.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_property.h">
                        </File>
index f7038e610f1d22427687acae631be71ee8945ef9..b42642c774f938cdb89d70e7663021b059033a48 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\BLI_heap.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\intern\BLI_kdtree.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\BLI_linklist.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\fileops.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\intern\fnmatch.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\freetypefont.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\BLI_fileops.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\BLI_fnmatch.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\BLI_ghash.h">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\BLI_jitter.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\BLI_kdtree.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\BLI_linklist.h">
                        </File>
index b7518c0bc823d2a5dc102c82ae2439824e9b432e..b4daf386c26f7bfb154f37b88103d42d24669a5e 100644 (file)
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr"
-                               PreprocessorDefinitions="_DEBUG,WIN32,_LIB,WITH_QUICKTIME"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
+                               PreprocessorDefinitions="_DEBUG,WIN32,_LIB,WITH_QUICKTIME,WITH_DDS"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="1"
                                DefaultCharIsUnsigned="TRUE"
                        <Tool
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr"
-                               PreprocessorDefinitions="NDEBUG,WIN32,_LIB,WITH_QUICKTIME"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
+                               PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_QUICKTIME;WITH_DDS"
                                StringPooling="TRUE"
                                RuntimeLibrary="0"
                                EnableFunctionLevelLinking="TRUE"
index f8d88f8640edd528a07c0a2836cdf2c725ef3b16..20d787112d4cd3dd2817db4584ae749a86f08b48 100644 (file)
@@ -525,6 +525,9 @@ DNA_makesdna.exe dna.c
                        <File
                                RelativePath="..\..\..\source\blender\makesdna\DNA_packedFile_types.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\makesdna\DNA_particle_types.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\makesdna\DNA_property_types.h">
                        </File>
index 2383f41b69bea504d24d857e6cdb3be5bbf4adeb..021d8c2c82a005d682048eb3e48990148e2b2537 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\render\intern\source\sss.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\render\intern\source\strand.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\render\intern\source\texture.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\render\intern\include\sss.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\render\intern\include\strand.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\render\intern\include\texture.h">
                        </File>
index 73e341a5bb4988ca9bb9b30b78c48d3561cf6d20..9c03b21f1a82c689a6fbd595368fe9621f1ee821 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\src\editoops.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\src\editparticle.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\editscreen.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BIF_editoops.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\include\BIF_editparticle.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BIF_editsca.h">
                        </File>
index c55e62be003ca9922dfbfeeae090ae1b2b89f22e..f608accf2b02af211fca73681c02439bc18b0bc4 100644 (file)
@@ -44,7 +44,7 @@ ifeq ($(OS),beos)
    EXT1=".zip"
    COMPRESS=""
    EXT2=""
-   NOPLUGINS="true"
+   NOPLUGINS?=true
 endif
 
 ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris"))
@@ -55,6 +55,11 @@ ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris"))
    COMPRESS="bzip2"
    COMPRESSFLAGS="-f"
    EXT2=".bz2"
+   ifeq ($(OS), solaris)
+     ifeq ($(CPU), i386)
+       NOPLUGINS?=true
+     endif
+   endif
 endif
 
 ifeq ($(OS),windows)
@@ -62,8 +67,8 @@ ifeq ($(OS),windows)
    TARFLAGS="-r9"
    EXT0=".exe"
    EXT1=".zip"
-   NOPLUGINS="true"
-   NOSTRIP="true"
+   NOPLUGINS?=true
+   NOSTRIP?=true
 endif
 
 ifeq ($(OS),darwin)
index d34acb7be0408739fc11320407a7ada337b11a48..d447b3b4f2c61f712cee19c4447627b8f29c1054 100644 (file)
Binary files a/release/datafiles/blenderbuttons and b/release/datafiles/blenderbuttons differ
index 8d67a88f679aae5ad652f665feb290e7a1b830d6..c39c26b063dbea88bbe8c418903cfba56d257a94 100644 (file)
Binary files a/release/datafiles/preview.blend and b/release/datafiles/preview.blend differ
index 0ff8e178ac1c66b9b986a5950992e0b75afc8c37..8ee1aa6c7070f8c07ee61f2102ba535597d76ded 100644 (file)
@@ -11,6 +11,8 @@ def Error_NoMeshUvActive():
        Draw.PupMenu('Error%t|Active object is not a mesh with texface')
 def Error_NoMeshMultiresEdit():
        Draw.PupMenu('Error%t|Unable to complete action with multires enabled')
+def Error_NoMeshFaces():
+       Draw.PupMenu('Error%t|Mesh has no faces')
 
 # File I/O messages
 def Error_NoFile(path):
diff --git a/release/scripts/flt_defaultp.py b/release/scripts/flt_defaultp.py
new file mode 100644 (file)
index 0000000..5dca8ba
--- /dev/null
@@ -0,0 +1 @@
+pal = [-256,0,16711680,-16777216,-19529984,-19726592,-19923200,-20119808,-20316416,-20578560,-20840704,-21102848,-21364992,-21692672,-22020352,-22413568,-22806784,-23200000,-23658752,-24117504,-24641792,-25166080,-25755904,-26411264,-27066624,-27787520,-28573952,-29425920,-30343424,-31326464,-32375040,-33489152,-354550016,-371458304,-388366592,-405274880,-422183168,-439156992,-456130816,-473104640,-506855680,-540672256,-574488832,-608305408,-642121984,-676004096,-709886208,-760611072,-811335936,-862060800,-912851200,-980418816,-1048051968,-1115685120,-1183383808,-1267925248,-1352466688,-1453850880,-1555300608,-1656815872,-1775173888,-1893597440,-2028863744,2130771712,-1010376448,-1043996416,-1077681920,-1111367424,-1145052928,-1178738432,-1229201152,-1279663872,-1330126592,-1380654848,-1431183104,-1498488576,-1565794048,-1633165056,-1700536064,-1784684288,-1868832512,-1969823488,-2070814464,2123096320,2005262592,1887428864,1752752384,1601298688,1449779456,1281417472,1096278272,911073536,709026048,490201344,254533888,2023680,-1380857856,-1397700608,-1431320576,-1464940544,-1498560512,-1532180480,-1565865984,-1599551488,-1650014208,-1700476928,-1750939648,-1801402368,-1851865088,-1919170560,-1986476032,-2053781504,-2121086976,2089797632,2005649408,1904723968,1803798528,1686030336,1568262144,1450493952,1315883008,1164494848,1013041152,844810240,659736576,457885696,239192064,3655680,-1767919872,-1784762624,-1801605376,-1818448128,-1852068096,-1885688064,-1919308032,-1952928000,-1986547968,-2020167936,-2070565120,-2120962304,2123542272,2073079552,2022616832,1955376896,1888136960,1820897024,1736879872,1652797184,1568714496,1467854592,1366994688,1249357568,1131654912,997175040,862695168,711372544,560049920,391950080,207007488,5287680,2139657728,2122880512,2106103296,2089326080,2072548864,2055771648,2022217216,1988662784,1955108352,1921553920,1887933952,1854313984,1803916800,1753519616,1703122432,1652725248,1602328064,1535153664,1467979264,1400804864,1316853248,1232901632,1148950016,1048221184,947426816,846632448,729060864,611489280,477140480,326014464,174888448,6919680,1837268224,1820491008,1803713792,1786936576,1770159360,1753382144,1736604928,1719827712,1686273280,1652718848,1619164416,1585609984,1552055552,1518501120,1468169472,1417837824,1367506176,1317174528,1266842880,1199734016,1132625152,1065516288,998407424,914521344,830635264,729971968,629308672,528645376,411204864,293764352,159546624,8551680,-2086957824,-2103735040,-2120512256,-2137289472,2140900608,2107346176,2073791744,2040237056,2006682368,1973127680,1939572992,1906018304,1855686400,1805354496,1755022592,1704690688,1654358784,1587249664,1520140544,1453031424,1369145088,1285258496,1201371904,1100708096,1000044288,882603264,765162240,630943744,496725248,345729536,177956608,10183680,-1699438080,-1716215552,-1732993024,-1766547712,-1800102400,-1833657088,-1867211776,-1900766464,-1934321152,-1967875840,-2018207744,-2068539904,-2118872064,2125763072,2058653696,1991544320,1924434944,1857325568,1773438720,1689551872,1588887808,1488223744,1387559424,1270117888,1152676352,1018457600,884238592,733242368,565468672,397694976,213144064,11815680,-1311918848,-1345473536,-1379028224,-1412582912,-1446137600,-1479692544,-1513247488,-1546802432,-1597134592,-1647466752,-1697798912,-1748131072,-1798463488,-1865573120,-1932682752,-1999792384,-2083679232,2127400960,2043513856,1942849536,1842184960,1724743168,1607301376,1473082112,1338862848,1187866112,1020092160,852317952,667766528,466437632,248331264,13447680,-924399104,-957954048,-991508992,-1025063936,-1058618880,-1092173824,-1142505984,-1192838144,-1243170560,-1293502976,-1343835392,-1410945024,-1478054656,-1545164544,-1629051648,-1712938752,-1796826112,-1897490688,-1998155264,-2098820096,2078705152,1961262848,1827043328,1676046336,1525049344,1357274880,1172722944,971393792,753287168,518403072,283518720,15079680,-570434304,-603989248,-637544192,-671099136,-704654080,-754986496,-805318912,-855651328,-905983744,-973093632,-1040203520,-1107313408,-1174423296,-1258310656,-1342198016,-1442862848,-1543527680,-1644192512,-1761634816,-1879077120,-2013296896,2147450624,1996453376,1828678656,1660903936,1476351744,1275022080,1056914944,822030336,570368256,301928704,16711680,-503325440,-536880384,-570435328,-603990272,-637545216,-671100416,-721432832,-771765248,-822097664,-872430336,-922763008,-989872896,-1056982784,-1124092928,-1191203072,-1275090688,-1358978304,-1459643136,-1560308224,-1660973312,-1778415872,-1895858432,-2030078464,2113891328,1962893824,1795118848,1610566400,1426013696,1224683520,1006575872,771690752,520028160,-452993792,-469771520,-503326464,-536881408,-570436352,-603991552,-637546752,-671101952,-721434368,-771767040,-822099712,-872432384,-922765056,-989875200,-1056985344,-1124095744,-1191206144,-1275093760,-1358981632,-1459646720,-1560312064,-1677754624,-1795197440,-1912640512,-2046860800,2097108736,1946110720,1778335232,1593782272,1392451840,1174343936,939458560,-419439360,-436217088,-452994816,-469772544,-503327488,-536882688,-570437888,-603993088,-637548288,-671103744,-721436416,-771769088,-822101760,-872434688,-922767616,-989878016,-1056988416,-1124098816,-1207986688,-1291874560,-1375762688,-1476428032,-1577093632,-1694536704,-1811979776,-1946200320,-2080421120,2063547904,1912549376,1744773376,1560219904,1358888960,-385884928,-402662656,-419440384,-436218112,-452995840,-469773824,-503329024,-536884224,-570439424,-603994880,-637550336,-671105792,-721438464,-771771392,-822104320,-872437504,-922770688,-989881088,-1056991744,-1124102400,-1191213312,-1275101440,-1358989824,-1459655680,-1560321536,-1677764864,-1795208448,-1912652288,-2046873600,2097094912,1946095872,1778319360,-335553280,-352331008,-369108736,-385886464,-402664192,-419442176,-436220160,-452998144,-486553344,-520108800,-553664256,-587219712,-620775168,-654330880,-687886592,-738219776,-788552960,-838886144,-889219584,-939553024,-1006663936,-1073774848,-1140886016,-1224774656,-1308663296,-1392552192,-1493218560,-1593885184,-1711329280,-1828773632,-1962995456,-2097217536,-285221632,-301999360,-318777088,-335554816,-352332544,-369110528,-385888512,-402666496,-419444480,-436222720,-453000960,-469779200,-503334656,-536890368,-570446080,-604002048,-637558016,-671113984,-721447424,-771780864,-822114560,-872448256,-922782208,-989893632,-1057005056,-1124116736,-1191228672,-1275118080,-1359007744,-1459674880,-1560342272,-1677787136,-234889984,-234890496,-251668224,-268445952,-285223680,-302001664,-318779648,-335557632,-352335616,-369113856,-385892096,-402670336,-419448576,-436227072,-453005568,-469784320,-503340288,-536896256,-570452480,-604008704,-637565184,-671121664,-704678400,-755012608,-805346816,-855681280,-906016000,-973128192,-1040240640,-1107353344,-1174466304,-1258356736,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-251673344,-268451584,-285229824,-302008064,-318786560,-335565056,-352343808,-369122560,-385901312,-402680320,-419459328,-436238592,-453017856,-486574592,-520131584,-553688576,-587245824,-620803328,-654361088,-687919104,-738254592,-788590336,-838926336,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-234896128,-234897152,-234898176,-234899200,-234900480,-234901760,-234903296,-234904832,-234906368,-234908160,-234909952,-234912000,-251691264,-268470784,-285250560,-302030336,-318810368,-335590656,-352371200,-369152000,-385933056,-402714368,-419495936,-8960,-9472,-9984,-10496,-11008,-11776,-12544,-13312,-14080,-15104,-16128,-17152,-18176,-19456,-20736,-22272,-23808,-25344,-27136,-28928,-30976,-33024,-35328,-37888,-40448,-43264,-46336,-49664,-53248,-57088,-61184,-65536,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-930816,-931584,-932608,-933632,-934656,-935680,-936960,-938240,-939776,-941312,-1008384,-1075712,-1143040,-1210624,-1278208,-1346048,-1414144,-1482240,-1550592,-1619200,-1688064,-1757184,-1826560,-1896192,-2031616,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-996352,-1062656,-1129216,-1195776,-1262336,-1328896,-1395712,-1462528,-1529600,-1596672,-1663744,-1731072,-1798400,-1865984,-1999104,-2132480,-2266112,-2399744,-2533632,-2667776,-2867712,-3067904,-3268352,-3469056,-3670016,-926464,-992512,-1058560,-1124608,-1190656,-1256960,-1323264,-1389568,-1455872,-1522432,-1588992,-1655552,-1722112,-1788928,-1855744,-1988352,-2120960,-2253568,-2386432,-2519296,-2652416,-2785536,-2984448,-3183616,-3382784,-3582208,-3847424,-4112896,-4378624,-4644608,-4976384,-5308416,-1188608,-1254656,-1320704,-1386752,-1452800,-1519104,-1585408,-1651712,-1718016,-1784576,-1851136,-1983232,-2115328,-2247680,-2380032,-2512640,-2645248,-2777856,-2976256,-3174656,-3373312,-3571968,-3836416,-4101120,-4365824,-4630784,-4961536,-5292544,-5689344,-6086400,-6483712,-6946816,-1385216,-1451264,-1517312,-1583360,-1649408,-1715712,-1782016,-1848320,-1980160,-2112256,-2244352,-2376448,-2508544,-2640896,-2838784,-3036928,-3235072,-3433216,-3631616,-3895552,-4159744,-4423936,-4688384,-5018624,-5348864,-5744896,-6141184,-6537728,-7000064,-7462656,-7991040,-8585216,-1581824,-1647872,-1713920,-1779968,-1846016,-1977856,-2109696,-2241536,-2373376,-2505472,-2637568,-2769664,-2967296,-3165184,-3363072,-3561216,-3759360,-4023040,-4286976,-4550912,-4880640,-5210368,-5540352,-5936128,-6331904,-6793472,-7255296,-7782912,-8310784,-8904448,-9563904,-10223616,-1712896,-1778944,-1844992,-1976576,-2108160,-2240000,-2371840,-2503680,-2635520,-2767616,-2965248,-3162880,-3360512,-3558400,-3821824,-4085504,-4349184,-4612864,-4942336,-5271808,-5667072,-6062336,-6457856,-6919168,-7380480,-7907584,-8434944,-9028096,-9687040,-10346240,-11071232,-11862016,-1843968,-1975552,-2107136,-2238720,-2370304,-2502144,-2633984,-2765824,-2963200,-3160832,-3358464,-3556096,-3753728,-4017152,-4280576,-4544256,-4873472,-5202688,-5532160,-5927168,-6322432,-6783232,-7244288,-7771136,-8297984,-8890624,-9549056,-10207744,-10932224,-11722496,-12578560,-13500416,-1975040,-2106624,-2238208,-2369792,-2501376,-2633216,-2830592,-3027968,-3225344,-3422976,-3620608,-3883776,-4146944,-4410368,-4673792,-5003008,-5332224,-5726976,-6121984,-6582528,-7043328,-7504128,-8030720,-8623104,-9215488,-9873664,-10597632,-11387392,-12242944,-13164288,-14085888,-15138816,-2237184,-2368768,-2500352,-2631936,-2763520,-2960896,-3158272,-3355648,-3553024,-3816192,-4079360,-4342528,-4605696,-4934656,-5263616,-5658368,-6053120,-6447872,-6908416,-7368960,-7895296,-8421632,-9013760,-9671680,-10329600,-11053312,-11842816,-12698112,-13619200,-14606080,-15658752,-16777216]
\ No newline at end of file
index 283c24a3ad01dbc08bc49fa701979a1c7120107b..033a03f1163af10c777daf4cfa6aea9e400434f1 100644 (file)
@@ -1,45 +1,25 @@
 #!BPY
 """ Registration info for Blender menus:
 Name: 'OpenFlight (.flt)...'
-Blender: 237
+Blender: 245
 Group: 'Export'
 Tip: 'Export to OpenFlight v16.0 (.flt)'
 """
 
-__author__ = "Greg MacDonald"
-__version__ = "1.2 10/20/05"
+__author__ = "Greg MacDonald, Geoffrey Bantle"
+__version__ = "2.0 11/21/07"
 __url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
 __bpydoc__ = """\
 This script exports v16.0 OpenFlight files.  OpenFlight is a
 registered trademark of MultiGen-Paradigm, Inc.
 
-Run from "File->Export" menu. 
-
-Options are available from Blender's "Scripts Config Editor," accessible through
-the "Scripts->System" menu from the scripts window.
-
-Features:<br>
-* Heirarchy retained.<br>
-* Normals retained.<br>
-* First texture exported.<br>
-* Diffuse material color is exported as the face color, material color, or both
-depending on the option settings.<br>
-* Double sided faces are exported as two faces.<br>
-* Object transforms exported.
-
-Things To Be Aware Of:<br>
-* Object names are exported, not mesh or data names.
-* Material indices that don't have a material associated with them will confuse the
-exporter. If a warning appears about this, correct it by deleting the offending
-material indices in Blender.
-
-What's Not Handled:<br>
-* Animations.<br>
-* Vetex colors.<br>
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/Export/openflight_flt
 """
 
 # flt_export.py is an OpenFlight exporter for blender.
-# Copyright (C) 2005 Greg MacDonald
+#
+# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -56,29 +36,87 @@ What's Not Handled:<br>
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 import Blender
+from Blender import Modifier
+import os.path
+import flt_properties
+import flt_defaultp as defaultp
 from flt_filewalker import FltOut
+from flt_filewalker import FileFinder
+from flt_properties import *
+import shutil
+
+FF = FileFinder()
+records = process_recordDefs()
 
 class ExporterOptions:
        def __init__(self):
-               self.defaults = { 'Diffuse Color To OpenFlight Material': False,
-                                                 'Diffuse Color To OpenFlight Face': True}
+               self.verbose = 1
+               self.tolerance = 0.001
+               self.writevcol = True
                
-               d = Blender.Registry.GetKey('flt_export', True)
+               #new stuff
+               self.export_shading = 0
+               self.shading_default = 45.0
+               self.basepath = os.path.dirname(Blender.Get('filename'))
+               self.scale = 1.0
                
-               if d == None or d.keys() != self.defaults.keys():
-                       d = self.defaults
-                       Blender.Registry.SetKey('flt_export', d, True)
+               #set externals path
+               if(os.path.exists(os.path.join(self.basepath,'externals'))):
+                       self.externalspath = os.path.join(self.basepath,'externals')
+               else:
+                       self.externalspath = self.basepath 
                
-               self.verbose = 1
-               self.tolerance = 0.001
-               self.use_mat_color = d['Diffuse Color To OpenFlight Material']
-               self.use_face_color = d['Diffuse Color To OpenFlight Face']
+               self.doxrefs = 1
+               
+               #texture options
+               if(os.path.exists(os.path.join(self.basepath,'textures'))):
+                       self.texturespath = os.path.join(self.basepath,'textures')
+               else:
+                       self.texturespath = self.basepath
+               
+               #misc
+               self.write_attrib_files = 0
+               self.copy_textures = 0
+               self.export_transform = 0
+               self.flattenmesh = False
                
+               self.xapp = 1
+               reg = Blender.Registry.GetKey('flt_export',1)
+               if(reg and 'xappath' in reg.keys()):
+                       self.xappath = reg['xappath']
+               else:
+                       self.xappath = ''
 options = ExporterOptions()
+tex_files = dict() #a list of (possibly) modified texture path names
+
+tex_layers = ['Layer0', 'Layer1', 'Layer2', 'Layer3', 'Layer4', 'Layer5', 'Layer6', 'Layer7']
+mask = 2147483648
+mtexmasks = []
+for i in xrange(7):
+       mtexmasks.append(mask)
+       mask = mask / 2
 
 FLOAT_TOLERANCE = options.tolerance
 
+#need to move all this stuff to flt_properties.py.
 identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
+alltypes = [2,4,11,73,63,111]
+childtypes = { 
+       2 : [111,2,73,4,14,63],
+       4 : [111],
+       73 : [111,2,73,4,14,63],
+       63 : [],
+       14 : [111,2,73,4,14,63],
+       111 : []
+}
+recordlen = {
+       2: 44,
+       4: 28,
+       73: 80,
+       63: 216,
+       14: 384,
+       111: 156
+}
 
 def is_identity(m):
        for i in xrange(4):
@@ -102,13 +140,47 @@ class MaterialDesc:
                self.alpha = 1.0 # Range is [0.0, 1.0]
 
 class VertexDesc:
-       def __init__(self, co=None, no=None, uv=None):
+       def __init__(self, co=None, no=None, uv=None, fltindex=None,cindex=None):
                if co: self.x, self.y, self.z = tuple(co)
                else: self.x = self.y = self.z = 0.0
                if no: self.nx, self.ny, self.nz = tuple(no)
                else: self.nx = self.ny = self.nz = 0.0
                if uv: self.u, self.v = tuple(uv)
                else: self.u = self.v = 0.0
+               if cindex: self.cindex = cindex
+               else: self.cindex = 127
+               self.fltindex = fltindex
+               self.accum = 0
+
+class shadowVert:
+       def __init__(self,bvert,object,world,normal):
+                global options
+               
+               self.co = Blender.Mathutils.Vector(bvert.co[0],bvert.co[1],bvert.co[2])
+                #if world:
+               #       vec = self.co
+               #       vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+               #       self.co =  Blender.Mathutils.TranslationMatrix(vec) * (self.co * object.getMatrix('worldspace'))
+               
+               if normal:
+                        #if world:
+                       #       self.no = Blender.Mathutils.Vector(normal * object.getMatrix('worldspace')).normalize()
+                       #else:
+                       self.no = Blender.Mathutils.Vector(normal[0],normal[1],normal[2])
+                       
+               else:
+                       #if world:
+                               #self.no = Blender.Mathutils.Vector(bvert.no * object.getMatrix('worldspace')).normalize() 
+                       #else:
+                       self.no = Blender.Mathutils.Vector(bvert.no[0],bvert.no[1],bvert.no[2])
+                       
+               #do scaling factor
+               #if options.scale != 1.0:
+                       #self.co[0] = self.co[0] * options.scale
+                       #self.co[1] = self.co[1] * options.scale
+                       #self.co[2] = self.co[2] * options.scale
+                       
+               self.index = bvert.index
 
 class GlobalResourceRepository:
        def new_face_name(self):
@@ -121,44 +193,98 @@ class GlobalResourceRepository:
        def request_vertex_desc(self, i):
                return self.vertex_lst[i]
 
-       def request_vertex_index(self, desc):
-               match = None
-               for i, v in enumerate(self.vertex_lst):
-                       if\
-                       abs(v.x - desc.x) > FLOAT_TOLERANCE or\
-                       abs(v.y - desc.y) > FLOAT_TOLERANCE or\
-                       abs(v.z - desc.z) > FLOAT_TOLERANCE or\
-                       abs(v.nx - desc.nx) > FLOAT_TOLERANCE or\
-                       abs(v.ny - desc.ny) > FLOAT_TOLERANCE or\
-                       abs(v.nz - desc.nz) > FLOAT_TOLERANCE or\
-                       abs(v.u - desc.u) > FLOAT_TOLERANCE or\
-                       abs(v.v - desc.v) > FLOAT_TOLERANCE:
-                               pass
-                       else:
-                               match = i
-                               break
+       def request_vertex_index(self, object, mesh, face, vfindex, uvok,cindex):
 
-               if match != None:
-                       return match
+               flatShadeNorm = None
+               
+               if type(face) is list:
+                       vertex = face[vfindex]
+               elif str(type(face)) == "<type " + "'Blender MVert'>": 
+                       vertex = face
+               elif str(type(face)) == "<type " + "'Blender MEdge'>":
+                       if vfindex == 1:
+                               vertex = face.v1
+                       elif vfindex == 2:
+                               vertex = face.v2
+               elif str(type(face)) == "<type " + "'Blender MFace'>":
+                        if not face.smooth:
+                                flatShadeNorm = face.no
+                       vertex = face.v[vfindex]
+               else: 
+                       return None
+                                               
+               if not self.namehash.has_key(object.name):
+                       self.namehash[object.name] = dict()
+               indexhash = self.namehash[object.name]
+               
+               #export in global space? THIS HAS BEEN MADE REDUNDANT... REMOVE ME
+               if not options.export_transform:
+                       vertex = shadowVert(vertex,object,True,flatShadeNorm)
                else:
-                       self.vertex_lst.append(desc)
-                       return len(self.vertex_lst) - 1
-
-       def request_texture_index(self, filename):
+                        vertex = shadowVert(vertex,object,False,flatShadeNorm)
+        
+                
+               #Check to see if this vertex has been visited before. If not, add
+               if not indexhash.has_key(vertex.index):
+                       if uvok:
+                               newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex)
+                       else:
+                               newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex)
+                       
+                       indexhash[vertex.index] = [newvdesc]
+                       self.vertex_lst.append(newvdesc)
+                       self.nextvindex = self.nextvindex + 1
+                       return newvdesc.fltindex
+               
+               else:
+                       desclist = indexhash[vertex.index]
+                       if uvok: 
+                               faceu = face.uv[vfindex][0]
+                               facev = face.uv[vfindex][1]
+                       else:
+                               faceu = 0.0
+                               facev = 0.0
+                       for vdesc in desclist:
+                               if\
+                               abs(vdesc.x - vertex.co[0]) > FLOAT_TOLERANCE or\
+                               abs(vdesc.y - vertex.co[1]) > FLOAT_TOLERANCE or\
+                               abs(vdesc.z - vertex.co[2]) > FLOAT_TOLERANCE or\
+                               abs(vdesc.nx - vertex.no[0]) > FLOAT_TOLERANCE or\
+                               abs(vdesc.ny - vertex.no[1]) > FLOAT_TOLERANCE or\
+                               abs(vdesc.nz - vertex.no[2]) > FLOAT_TOLERANCE or\
+                               vdesc.cindex != cindex or\
+                               abs(vdesc.u - faceu) > FLOAT_TOLERANCE or\
+                               abs(vdesc.v - facev) > FLOAT_TOLERANCE:
+                                       pass
+                               else:
+                                       return vdesc.fltindex
+                               
+                       #if we get this far, we didnt find a match. Add a new one and return
+                       if uvok:
+                               newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex)
+                       else:
+                               newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex)
+                       indexhash[vertex.index].append(newvdesc)
+                       self.vertex_lst.append(newvdesc)
+                       self.nextvindex = self.nextvindex + 1
+                       return newvdesc.fltindex
+                                       
+                       
+       def request_texture_index(self, image):
                match = None
                for i in xrange(len(self.texture_lst)):
-                       if self.texture_lst[i] != filename:
+                       if self.texture_lst[i] != image:
                                continue
                        match = i
                        break
                if match != None:
                        return match
                else:
-                       self.texture_lst.append(filename)
+                       self.texture_lst.append(image)
                        return len(self.texture_lst) - 1
 
        def request_texture_filename(self, index):
-               return self.texture_lst[index]
+               return Blender.sys.expandpath(self.texture_lst[index].getFilename())
 
        def texture_count(self):
                return len(self.texture_lst)
@@ -239,7 +365,11 @@ class GlobalResourceRepository:
                return len(self.color_lst)
 
        def __init__(self):
+               #Vertex handling
                self.vertex_lst = []
+               self.nextvindex = 0
+               self.namehash = dict()
+               
                self.texture_lst = []
                self.material_lst = []
                self.color_lst = [[255, 255, 255]]
@@ -253,7 +383,6 @@ class Node:
                if self.object:
                        if options.verbose >= 2:
                                print '\t' * level[0], self.name, self.object.type
-
                level[0] += 1
                
                for child in self.children:
@@ -288,183 +417,530 @@ class Node:
                        self.header.fw.write_ushort(length+5)       # Length of record
                        self.header.fw.write_string(name, length+1) # name + zero terminator
 
+       def write_comment(self,comment):
+               length = len(comment)
+               if length >= 65535:
+                       comment = comment[:65530]
+                       length = len(comment)
+               
+               pad = (length % 4) - 1
+               if pad < 0: 
+                       pad = None
+                       reclength = length + 5
+               else:
+                       reclength = length + 5 + pad
+               
+               self.header.fw.write_short(31)                                  # Comment Opcode
+               self.header.fw.write_ushort(reclength)                  # Length of record is 4 + comment length + null terminator + pad
+               self.header.fw.write_string(comment,length+1)   # comment + zero terminator
+               if pad:
+                       self.header.fw.pad(pad)                                         # pad to multiple of 4 bytes
+               
        # Initialization sets up basic tree structure.
-       def __init__(self, parent, header, object, object_lst):
+       def __init__(self, parent, header, object,props):
+               global options
+               
                self.header = header
                self.object = object
                if object:
                        self.name = self.object.name
-                       self.matrix = self.object.getMatrix('localspace')
+                       if not options.export_transform:
+                               oloc = Blender.Mathutils.Vector(object.getLocation('worldspace'))
+                               vec = Blender.Mathutils.Vector(oloc[0] * options.scale, oloc[1] * options.scale, oloc[2] * options.scale) #scale
+                               self.matrix =  self.object.getMatrix('worldspace') *  Blender.Mathutils.TranslationMatrix(vec - oloc)                   
+                       else:
+                               self.matrix = self.object.getMatrix('localspace') #do matrix mult here.
+                       self.props = props
+                       self.child_objects = self.header.parenthash[object.name]
                else:
                        self.name = 'no name'
                        self.matrix = None
-
+                       self.props = None
+                       self.child_objects = self.header.child_objects
+               
                self.children = []
                self.parent = parent
                if parent:
                        parent.children.append(self)
-
-               left_over = object_lst[:]
-               self.child_objects = []
-
-               # Add children to child list and remove from left_over list.
                
-               # Pop is faster then remove
-               i = len(object_lst)
-               while i:
-                       i-=1
-                       if object_lst[i].parent == object:
-                               self.child_objects.append(left_over.pop(i))
-                       
                # Spawn children.
-               self.has_object_child = False # For Database class.
                for child in self.child_objects:                        
-                       if child.type == 'Mesh':
-                               BlenderMesh(self, header, child, left_over)
-                               self.has_object_child = True
-                       else: # Treat all non meshes as emptys
-                               BlenderEmpty(self, header, child, left_over)
-
+                       if(not child.restrictDisplay):
+                               childprops = None
+                               type = None
+                               if not child.properties.has_key('FLT'):
+                                       if child.type == 'Empty':
+                                               if child.DupGroup:
+                                                       childprops = FLTXRef.copy()
+                                                       type = 63
+                                               else:
+                                                       childprops = FLTGroup.copy()
+                                                       type = 2
+                                       elif child.type == 'Mesh':
+                                               if self.header.childhash[child.name] or not child.parent:
+                                                       childprops = FLTGroup.copy()
+                                                       type = 2
+                                               else:
+                                                       childprops = FLTObject.copy()
+                                                       type = 4
+                                                       
+                               else:
+                                       childprops = dict()
+                                       for prop in child.properties['FLT']:
+                                               childprops[prop] = child.properties['FLT'][prop]
+                                       type = child.properties['FLT']['type']
+                               
+                               if type in self.childtypes and type in alltypes:
+                                       Newnode = FLTNode(self,header,child,childprops,type)
+                                       if child.type == 'Mesh':
+                                               self.header.mnodes.append(Newnode)
 class FaceDesc:
        def __init__(self):
                self.vertex_index_lst = []
+               self.mface = None
                self.texture_index = -1
                self.material_index = -1
                self.color_index = 127
-       
-class BlenderMesh(Node):
-       def blender_export(self):
-               Node.blender_export(self)
-
-               mesh = self.object.getData()
-               mesh_hasuv = mesh.hasFaceUV()
-               # Gather materials and textures.
-               tex_index_lst = []
-               mat_index_lst = []
-               color_index_lst = []
-               materials = mesh.getMaterials()
-               
-               if not materials:
-                       materials = [Blender.Material.New()]
-               
-               for mat in materials:
-                       # Gather Color.
-                       if options.use_face_color:
-                               color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol()))
+               self.renderstyle = 0
+               self.twoside = 0
+               self.name = None #uses next FLT name if not set... fix resolution of conflicts!
+               
+               #Multi-Tex info. Dosn't include first UV Layer!
+               self.uvlayer = list() #list of list of tuples for UV coordinates.
+               self.images = list()  #list of texture indices for seperate UV layers
+               self.mtex = list()
+               self.subface = None #can either be 'Push' or 'Pop'
+
+def edge_get_othervert(vert, edge):
+       if edge.v1 == vert:
+               return edge.v2
+       elif edge.v2 == vert:
+               return edge.v1
+       return None
+
+class FLTNode(Node):
+       def walkLoop(self, targetvert, startvert, startedge, edgelist, visited, vedges, closeloop):
+               loop = [targetvert]
+               
+               curvert = startvert
+               curedge = startedge
+               visited[curedge] = True
+               found = False
+               
+               while not found:
+                       loop.append(curvert)
+                       disk = vedges[curvert.index]
+                       if not closeloop:
+                               if len(disk) == 1:
+                                       visited[curedge] = True
+                                       break
                        else:
-                               color_index_lst.append(127) # white
-                       # Gather Texture.
-                       mtex_lst = mat.getTextures()
-
-                       index = -1
-                       mtex = mtex_lst[0] # Not doing multi-texturing at the moment.
-                       if mtex != None:
-                               tex = mtex_lst[0].tex
-                               if tex != None:
-                                       image = tex.getImage()
-                                       if image != None:
-                                               filename = image.getFilename()
-                                               index = self.header.GRR.request_texture_index(filename)
-
-                       tex_index_lst.append(index)
-
-                       # Gather Material
-                       mat_desc = MaterialDesc()
-                       mat_desc.name = mat.name
-                       mat_desc.alpha = mat.getAlpha()
-                       mat_desc.shininess = mat.getSpec() * 64.0   # 2.0 => 128.0
-                       if options.use_mat_color:
-                               mat_desc.diffuse = mat.getRGBCol()
+                               if len(disk) < 2: #what?
+                                       visited[curedge] = True
+                                       return None
+                       
+                       if disk[0] == curedge:
+                               curedge = disk[1]
                        else:
-                               mat_desc.diffuse = [1.0, 1.0, 1.0]
+                               curedge = disk[0]
+                       if curedge.v1.index == curvert.index:
+                               curvert = curedge.v2
+                       else:
+                               curvert = curedge.v1
 
-                       mat_desc.specular = mat.getSpecCol()
-                       amb = mat.getAmb()
-                       mat_desc.ambient = [amb, amb, amb]
-                       emit = mat.getEmit()
-                       mat_desc.emissive = [emit, emit, emit]
+                       visited[curedge] = True
+                       
+                       if(curvert == targetvert):
+                               found = True
+               
+               return loop
+       
+       def buildVertFaces(self,vertuse):
+               for vert in self.exportmesh.verts:
+                       if vertuse[vert.index][0] == False and vertuse[vert.index][1] == 0:
+                               face_desc = FaceDesc()
+                               face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, vert, 0,0,0))
+                               face_desc.renderstyle = 3
+                               face_desc.color_index = 227
+                               self.face_lst.append(face_desc)
 
-                       mat_index_lst.append(self.header.GRR.request_material_index(mat_desc))
+       def buildEdgeFaces(self,vertuse):
+               for edge in self.exportmesh.edges:
+                       v1 = vertuse[edge.v1.index]
+                       v2 = vertuse[edge.v2.index]
+                       if v1[0] == False and v2[0] == False:
+                               if v1[1] == 1 and v2[1] == 1:
+                                       face_desc = FaceDesc()
+                                       face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 1, 0,0))
+                                       face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 2, 0,0))                                     
+                                       face_desc.renderstyle = 3
+                                       face_desc.color_index = 227
+                                       self.face_lst.append(face_desc)
+
+
+       def vertwalk(self, startvert, loop, disk, visited):
+               visited[startvert] = True
+               for edge in disk[startvert]:
+                       othervert = edge_get_othervert(startvert, edge)
+                       if not visited[othervert]:
+                               loop.append(othervert)
+                               self.vertwalk(othervert,loop,disk,visited)
+
+       def buildOpenFacesNew(self, vertuse):
+               wireverts = list()
+               wiredges = list()
+               visited = dict()
+               disk = dict()
+               loops = list()
+               
+               for edge in self.exportmesh.edges:
+                       v1 = vertuse[edge.v1.index]
+                       v2 = vertuse[edge.v2.index]
+                       if v1[0] == False and v2[0] == False:
+                               if v1[1] < 3 and v2[1] < 3:
+                                       wireverts.append(edge.v1)
+                                       wireverts.append(edge.v2)
+                                       wiredges.append(edge)
+                               
+               #build disk data
+               for vert in wireverts:
+                       visited[vert] = False
+                       disk[vert] = list()
+               for edge in wiredges:
+                       disk[edge.v1].append(edge)
+                       disk[edge.v2].append(edge)
+               
+               #first pass: do open faces
+               for vert in wireverts:
+                       if not visited[vert] and vertuse[vert.index][1] == 1:
+                               visited[vert] = True
+                               loop = [vert]
+                               othervert = edge_get_othervert(vert, disk[vert][0])
+                               self.vertwalk(othervert, loop, disk, visited)
+                               if len(loop) > 2: loops.append( ('Open', loop) )
+
+               for vert in wireverts:
+                       if not visited[vert]:
+                               visited[vert] = True
+                               loop = [vert]
+                               othervert = edge_get_othervert(vert,disk[vert][0])
+                               self.vertwalk(othervert, loop, disk, visited)
+                               if len(loop) > 2: loops.append( ('closed', loop) )
+                               
+               #now go through the loops and append.
+               for l in loops:
+                       (type, loop) = l
+                       face_desc = FaceDesc()
+                       for i,vert in enumerate(loop):
+                               face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,loop,i,0,0))
+                               if type  == 'closed':
+                                       face_desc.renderstyle = 2
+                               else:
+                                       face_desc.renderstyle = 3
+                               face_desc.color_index = 227
+                       self.face_lst.append(face_desc)
 
-               # Faces described as lists of indices into the GRR's vertex_lst.
-               for face in mesh.faces:
-                       
-                       face_v = face.v # Faster access
-                       
-                       # Create vertex description list for each face.
-                       if mesh_hasuv:
-                               vertex_lst = [VertexDesc(v.co, v.no, face.uv[i]) for i, v in enumerate(face_v)]
-                       else:
-                               vertex_lst = [VertexDesc(v.co, v.no) for i, v in enumerate(face_v)]
+       def sortFLTFaces(self,a,b):
+               aindex = a.getProperty("FLT_ORIGINDEX")
+               bindex = b.getProperty("FLT_ORIGINDEX")
+               
+               if aindex > bindex:
+                       return 1
+               elif aindex < bindex:
+                       return -1
+               return 0
+
+       def buildNormFaces(self):
+               
+               global options
+               meshlayers = self.exportmesh.getUVLayerNames()
+               oldlayer = self.exportmesh.activeUVLayer
+               uvok = 0
+               subfaceok = 0
+               subfacelevel = 0
+               
+               #special case
+               if self.exportmesh.faceUV and len(meshlayers) == 1:
+                       uvok = 1
+               elif self.exportmesh.faceUV and tex_layers[0] in meshlayers:
+                       self.exportmesh.activeUVLayer = tex_layers[0] 
+                       uvok = 1
+               
+               #Sort faces according to the subfaces/FLT indices
+               if "FLT_ORIGINDEX" in self.exportmesh.faces.properties and "FLT_SFLEVEL" in self.exportmesh.faces.properties:
+                       exportfaces = list()
+                       for face in self.exportmesh.faces:
+                               exportfaces.append(face)
+                       exportfaces.sort(self.sortFLTFaces)
+                       subfaceok = 1
+               else:
+                       exportfaces = self.exportmesh.faces
                        
+               # Faces described as lists of indices into the GRR's vertex_lst.
+               for face in exportfaces:
+                       descs = list()
+                       #first we export the face as normal
                        index_lst = []
-                       for vert_desc in vertex_lst:
-                               index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
-                       
+                       face_v = face.verts
+                       for i, v in enumerate(face_v):
+                               index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,face,i,uvok,0))
                        face_desc = FaceDesc()
                        face_desc.vertex_index_lst = index_lst
+                       face_desc.mface = face
+                       descs.append(face_desc)
                        
-                       if face.materialIndex < len(materials):
-                               face_desc.color_index    = color_index_lst[face.materialIndex]
-                               face_desc.texture_index  = tex_index_lst[face.materialIndex]
-                               face_desc.material_index = mat_index_lst[face.materialIndex]
-                       else:
-                               if options.verbose >=1:
-                                       print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.'
+                       #deal with subfaces                     
+                       if subfaceok:
+                               fsflevel = face.getProperty("FLT_SFLEVEL")
+                               for face_desc in descs:
+                                       if fsflevel > subfacelevel:
+                                               face_desc.subface = 'Push'
+                                               subfacelevel = fsflevel
+                                       elif fsflevel < subfacelevel:
+                                               face_desc.subface = 'Pop'
+                                               subfacelevel = fsflevel
+               
+                       
+                       if uvok and (face.mode & Blender.Mesh.FaceModes.TWOSIDE):
+                               face_desc.renderstyle = 1
+                       for face_desc in descs: 
+                               if "FLT_COL" in self.exportmesh.faces.properties:
+                                       color_index = face.getProperty("FLT_COL")
+#                                      if(color_index < 127):
+#                                              color_index = 127 #sanity check for face color indices
+                                       if(color_index == 0):
+                                               color_index = 127
+                                       face_desc.color_index = color_index
+                               else:
+                                       face_desc.color_index = 127
+                               if "FLT_ID" in self.exportmesh.faces.properties:
+                                       face_desc.name = face.getProperty("FLT_ID") #need better solution than this.
+                               
+                               self.face_lst.append(face_desc)
+               if uvok:                
+                       self.exportmesh.activeUVLayer = oldlayer
 
-                       self.face_lst.append(face_desc)
+       def buildTexData(self):
+               
+               meshlayers = self.exportmesh.getUVLayerNames()
+               oldlayer = self.exportmesh.activeUVLayer
+               uvok = 0
+               
+               if self.exportmesh.faceUV and len(meshlayers) == 1:
+                       uvok = 1
+               if self.exportmesh.faceUV and tex_layers[0] in meshlayers:
+                       self.exportmesh.activeUVLayer = tex_layers[0] 
+                       uvok = 1
+               
+               if uvok: 
+                       #do base layer. UVs have been stored on vertices directly already.
+                       for i, face in enumerate(self.face_lst):
+                               if face.mface:
+                                       mface = face.mface
+                                       image = mface.image
+                                       if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]:
+                                               index = self.header.GRR.request_texture_index(image)
+                                       else:
+                                               index = -1
+                                       face.texture_index = index
+
+                       for i, face in enumerate(self.face_lst):
+                               if face.mface:
+                                       mface_v = face.mface.v
+                                       for v in mface_v:
+                                               face.uvlayer.append([])
                        
-                       # Export double sided face as 2 faces with opposite orientations.
-                       if mesh_hasuv and face.mode & Blender.NMesh.FaceModes['TWOSIDE']:
-                               # Create vertex description list for each face. they have a face mode, so we know they have a UV too.
-                               vertex_lst = [VertexDesc(v.co, -v.no, face.uv[i]) for i, v in enumerate(face_v)]
-                               vertex_lst.reverse() # Reversing flips the face.
+                       for layername in tex_layers[1:]:
+                               if layername in meshlayers:
+                                       self.exportmesh.activeUVLayer=layername
+                                       for i, face in enumerate(self.face_lst):
+                                               if face.mface:
+
+                                                       face.mtex.append(layername)
+                                                       mface = face.mface
+                                                       mface_v = mface.v
+                                                       image = mface.image
+                                               
+                                                       if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]:
+                                                               index = self.header.GRR.request_texture_index(image)
+                                                               face.images.append(index)
+                                                       else:
+                                                               face.images.append(-1)
+
+                                                       for j, v in enumerate(mface_v):
+                                                               face.uvlayer[j].append(tuple(mface.uv[j]))
+               if uvok:
+                       self.exportmesh.activeUVLayer = oldlayer
+       def blender_export(self):
+               global options
+               Node.blender_export(self)
+               if self.opcode == 111:
+                       self.exportmesh = Blender.Mesh.New()
+                       self.exportmesh.getFromObject(self.object.name)                 
+
+                       for vert in self.exportmesh.verts:
+                               if not options.export_transform:
+                                       vec = vert.co
+                                       vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+                                       vert.co =  Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace'))                                           
                                
-                               index_lst = []
-                               for vert_desc in vertex_lst:
-                                       index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
+                               if options.scale != 1.0:
+                                       vert.co = vert.co * options.scale
+
+                       if("FLT_VCOL") in self.mesh.verts.properties:
+                               for v in self.exportmesh.verts:
+                                       self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,v,0,0,v.getProperty("FLT_VCOL")))
+                       else:
+                               for v in self.mesh.verts:
+                                       self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.mesh,v,0,0,127))
+                       
+               
+               
+               elif self.mesh:
+                        orig_mesh = self.object.getData(mesh=True)
+                       self.exportmesh = Blender.Mesh.New()
+                       default = None
+
+
+                       if options.export_shading:
+                               mods = self.object.modifiers
+                               hasedsplit = False
+                               for mod in mods:
+                                       if mod.type == Blender.Modifier.Types.EDGESPLIT:
+                                               hasedsplit = True
+                                               break
+                               if not hasedsplit:
+                                       default = mods.append(Modifier.Types.EDGESPLIT)
+                                       default[Modifier.Settings.EDGESPLIT_ANGLE] = options.shading_default
+                                       default[Modifier.Settings.EDGESPLIT_FROM_ANGLE] = True
+                                       default[Modifier.Settings.EDGESPLIT_FROM_SHARP] = False
+                                       self.object.makeDisplayList()
+
+                       self.exportmesh.getFromObject(self.object.name)
+
+                       #recalculate vertex positions
+                       for vert in self.exportmesh.verts:
+                               if not options.export_transform:
+                                       vec = vert.co
+                                       vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+                                       vert.co =  Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace'))                                           
                                
-                               face_desc = FaceDesc()
-                               face_desc.vertex_index_lst = index_lst
-                               if face.materialIndex < len(materials):
-                                       face_desc.color_index = color_index_lst[face.materialIndex]
-                                       face_desc.texture_index = tex_index_lst[face.materialIndex]
-                                       face_desc.material_index = mat_index_lst[face.materialIndex]
-                               else:
-                                       if options.verbose >=1:
-                                               print 'Error: No material for material index. Delete abandoned material indices in Blender.'
-       
-                               self.face_lst.append(face_desc)
+                               if options.scale != 1.0:
+                                       vert.co = vert.co * options.scale                       
+                       
+                       flipped = self.object.getMatrix('worldspace').determinant()
+                       
+                       if not options.export_transform:
+                               self.exportmesh.calcNormals()
+                       
+
+                       if default:
+                                #remove modifier from list
+                               mods.remove(default)
+                               self.object.makeDisplayList()
+                               
+                       #build some adjacency data
+                       vertuse = list()
+                       wiredges = list()
+                       openends = list()
+                       for v in self.exportmesh.verts:
+                               vertuse.append([False,0])
+                       
+                       #build face incidence data
+                       for face in self.exportmesh.faces:
+                               for i, v in enumerate(face.verts):
+                                       vertuse[v.index][0] = True
+
+                       for edge in self.exportmesh.edges: #count valance
+                               vertuse[edge.v1.index][1] = vertuse[edge.v1.index][1] + 1
+                               vertuse[edge.v2.index][1] = vertuse[edge.v2.index][1] + 1
+
+                       #create all face types
+                       self.buildVertFaces(vertuse)
+                       self.buildEdgeFaces(vertuse)
+                       self.buildOpenFacesNew(vertuse)
+                       self.buildNormFaces()
+                       self.buildTexData()
+                       
+                       if not options.export_transform:
+                               if flipped < 0:
+                                       for vdesc in self.header.GRR.vertex_lst:
+                                               vdesc.accum = 0
+                                       for face in self.face_lst:
+                                               face.vertex_index_lst.reverse()
+                                               for vert in face.vertex_index_lst:
+                                                       self.header.GRR.vertex_lst[vert].accum = 1
+                                                       
+                                       for vdesc in self.header.GRR.vertex_lst:
+                                               if vdesc.accum:
+                                                       vdesc.nx = vdesc.nx * -1
+                                                       vdesc.ny = vdesc.ny * -1
+                                                       vdesc.nz = vdesc.nz * -1
+
 
        def write_faces(self):
+               sublevel = 0
                for face_desc in self.face_lst:
-                       face_name = self.header.GRR.new_face_name()
+                       if face_desc.name:
+                               face_name = face_desc.name
+                       else:
+                               face_name = self.header.GRR.new_face_name()
                        
+                       #grab the alpha value.
+                       alpha = 0
+                       if face_desc.texture_index > -1:
+                               try:
+                                       typestring = os.path.splitext(self.header.GRR.texture_lst[face_desc.texture_index].getFilename())[1]
+                                       if typestring == '.inta' or typestring == '.rgba':
+                                               alpha = 1
+                               except:
+                                       pass
+                                       
+                       if not alpha:
+                               for index in face_desc.images:
+                                       try:
+                                               typestring = os.path.splitext(self.header.GRR.texture_lst[index].getFilename())[1]
+                                               if typestring == '.inta' or typestring == '.rgba':
+                                                       alpha = 1
+                                       except:
+                                               pass
+                               
+                       if face_desc.subface:
+                               if face_desc.subface == 'Push':
+                                       self.header.fw.write_short(19)
+                                       self.header.fw.write_ushort(4)
+                                       sublevel += 1
+                               else:
+                                       self.header.fw.write_short(20)
+                                       self.header.fw.write_ushort(4)
+                                       sublevel -= 1
                        self.header.fw.write_short(5)                                   # Face opcode
                        self.header.fw.write_ushort(80)                                 # Length of record
                        self.header.fw.write_string(face_name, 8)                       # ASCII ID
                        self.header.fw.write_int(-1)                                    # IR color code
-                       self.header.fw.write_short(0)                                   # Relative priority
-                       self.header.fw.write_char(0)                                    # Draw type
+                       self.header.fw.write_short(0)                                                                   # Relative priority
+                       self.header.fw.write_char(face_desc.renderstyle)                # Draw type
                        self.header.fw.write_char(0)                                    # Draw textured white.
                        self.header.fw.write_ushort(0)                                  # Color name index
                        self.header.fw.write_ushort(0)                                  # Alt color name index
                        self.header.fw.write_char(0)                                    # Reserved
-                       self.header.fw.write_char(1)                                    # Template
+                       self.header.fw.write_char(alpha)                                    # Template
                        self.header.fw.write_short(-1)                                  # Detail tex pat index
                        self.header.fw.write_short(face_desc.texture_index)             # Tex pattern index
                        self.header.fw.write_short(face_desc.material_index)            # material index
                        self.header.fw.write_short(0)                                   # SMC code
-                       self.header.fw.write_short(0)                                   # Feature code
+                       self.header.fw.write_short(0)                                   # Feature                                       code
                        self.header.fw.write_int(0)                                     # IR material code
                        self.header.fw.write_ushort(0)                                  # transparency 0 = opaque
                        self.header.fw.write_uchar(0)                                   # LOD generation control
                        self.header.fw.write_uchar(0)                                   # line style index
-                       self.header.fw.write_int(0x00000000)                            # Flags
+                       self.header.fw.write_int(0)                            # Flags
                        self.header.fw.write_uchar(2)                                   # Light mode
+                       #self.header.fw.write_uchar(3)                                   # Light mode
+
                        self.header.fw.pad(7)                                           # Reserved
-                       self.header.fw.write_uint(-1)                                   # Packed color
-                       self.header.fw.write_uint(-1)                                   # Packed alt color
+                       self.header.fw.write_uint(0)                                   # Packed color
+                       self.header.fw.write_uint(0)                                   # Packed alt color
                        self.header.fw.write_short(-1)                                  # Tex map index
                        self.header.fw.write_short(0)                                   # Reserved
                        self.header.fw.write_uint(face_desc.color_index)                # Color index
@@ -473,7 +949,24 @@ class BlenderMesh(Node):
                        self.header.fw.write_short(-1)                                  # Shader index
 
                        self.write_longid(face_name)
-
+                       
+                       
+                       #Write Multitexture field if appropriate
+                       mtex = len(face_desc.mtex)
+                       if mtex:
+                               uvmask = 0
+                               for layername in face_desc.mtex:
+                                       mask = mtexmasks[tex_layers.index(layername)-1]
+                                       uvmask |= mask
+                               self.header.fw.write_ushort(52)                                                                 # MultiTexture Opcode
+                               self.header.fw.write_ushort(8 + (mtex * 8))             # Length
+                               self.header.fw.write_uint(uvmask)                                                               # UV mask
+                               for i in xrange(mtex):
+                                       self.header.fw.write_ushort(face_desc.images[i])                        # Tex pattern index
+                                       self.header.fw.write_ushort(0)                                                          # Tex effect
+                                       self.header.fw.write_ushort(0)                                                          # Tex Mapping index
+                                       self.header.fw.write_ushort(0)                                                          # Tex data. User defined
+                       
                        self.write_push()
 
                        # Vertex list record
@@ -484,72 +977,95 @@ class BlenderMesh(Node):
                        for vert_index in face_desc.vertex_index_lst:
                                # Offset into vertex palette
                                self.header.fw.write_int(vert_index*64+8)
-
+                       
+                       #UV list record
+                       if mtex:
+                               #length = 8 + (numverts * multitex * 8)
+                               self.header.fw.write_ushort(53)                                                                 # UV List Ocode
+                               self.header.fw.write_ushort(8 + (num_verts*mtex*8))                             # Record Length
+                               self.header.fw.write_uint(uvmask)                                                               # UV mask
+                               for i, vert_index in enumerate(face_desc.vertex_index_lst):
+                                       for uv in face_desc.uvlayer[i]:
+                                               self.header.fw.write_float(uv[0])                                               #U coordinate
+                                               self.header.fw.write_float(uv[1])                                               #V coordinate                           
                        self.write_pop()
+               #clean up faces at the end of meshes....
+               if sublevel:
+                       self.header.fw.write_short(20)
+                       self.header.fw.write_ushort(4)
+
+       def write_lps(self):
+               # Vertex list record
+               self.write_push()
+               self.header.fw.write_short(72)                        # Vertex list opcode
+               num_verts = len(self.vert_lst)
+               self.header.fw.write_ushort(4*num_verts+4)            # Length of record
 
+               for vert_index in self.vert_lst:
+                       # Offset into vertex palette
+                       self.header.fw.write_int(vert_index*64+8)
+               self.write_pop()
        def write(self):
-               if self.open_flight_type == 'Object':
-                       self.header.fw.write_short(4)               # Object opcode
-                       self.header.fw.write_ushort(28)             # Length of record
-                       self.header.fw.write_string(self.name, 8)   # ASCII ID
-                       self.header.fw.pad(16)
-       
-                       self.write_longid(self.name)
+               self.header.fw.write_short(self.opcode)
+               self.header.fw.write_ushort(recordlen[self.opcode])
+               exportdict = FLT_Records[self.opcode].copy()
+               for key in exportdict.keys():
+                       if self.props.has_key(key):
+                               exportdict[key] = self.props[key]
+
+                if self.opcode == 63 and options.externalspath:
+                               try:
+                                       exportdict['3t200!filename'] = os.path.join(options.externalspath,self.object.DupGroup.name+'.flt')
+                                       self.header.xrefnames.append(self.object.DupGroup.name)
+                               except:
+                                       pass
+               
+               for key in records[self.opcode]:
+                       (type,length,propname) = records[self.opcode][key]
+                       write_prop(self.header.fw,type,exportdict[propname],length)
+               
+               if self.props.has_key('comment'):
+                       self.write_comment(self.props['comment'])
                        
+               self.write_longid(self.name) #fix this!
+               
+               if options.export_transform or self.opcode == 63:
+                       #writing transform matrix....
                        self.write_matrix()
-                       
+
+               if self.opcode == 111:
+                       self.write_lps()
+               elif self.face_lst != [] or self.children:
+                       self.write_push()
                        if self.face_lst != []:
-                               self.write_push()
-               
+                               #self.write_push()
                                self.write_faces()
+                               #self.write_pop()
                
-                               self.write_pop()
-               else:
-                       self.header.fw.write_short(2)               # Group opcode
-                       self.header.fw.write_ushort(44)             # Length of record
-                       self.header.fw.write_string(self.name, 8)   # ASCII ID
-                       self.header.fw.pad(32)
-       
-                       self.write_longid(self.name)
-                       
-                       # Because a group can contain faces as well as children.
-                       self.write_push() 
-                       
-                       self.write_faces()
-                       
-                       for child in self.children:
-                               child.write()
-                       
+                       if self.children:
+                               #self.write_push()
+                               for child in self.children:
+                                       child.write()
+                               #self.write_pop()
                        self.write_pop()
-
-       def __init__(self, parent, header, object, object_lst):
-               Node.__init__(self, parent, header, object, object_lst)
-               self.face_lst = []
-               
-               if self.children:
-                       self.open_flight_type= 'Group'
-               else: # Empty list.
-                       self.open_flight_type = 'Object'
                        
-
-class BlenderEmpty(Node):
-       def write(self):
-               self.header.fw.write_short(2)               # Group opcode
-               self.header.fw.write_ushort(44)             # Length of record
-               self.header.fw.write_string(self.name, 8)   # ASCII ID
-               self.header.fw.pad(32)
-
-               self.write_longid(self.name)
-               
-               self.write_matrix()
+       def __init__(self, parent, header, object,props,type):
+               self.opcode = type #both these next two lines need to be in the node class....
+               self.childtypes = childtypes[self.opcode]
+               Node.__init__(self, parent, header, object,props)
+               self.face_lst = []
+               self.vert_lst = [] #for light points.
+               self.mesh = None
+               self.uvlayer = 0
+               self.flipx = False
+               self.flipy = False
+               self.flipz = False
                
-               if self.children: # != []
-                       self.write_push()
-       
-                       for child in self.children:
-                               child.write()
                                
-                       self.write_pop()
+               if self.object.type == 'Mesh':
+                       self.mesh = self.object.getData(mesh=True)
+                       if(self.mesh.faceUV):
+                               self.uvLayer = len(self.mesh.getUVLayerNames())
 
 class Database(Node):
        def write_header(self):
@@ -568,8 +1084,19 @@ class Database(Node):
                self.fw.write_int(0)            # projection type, 0 = flat earth
                self.fw.pad(30)
                self.fw.write_short(1)          # double precision
-               self.fw.pad(140)
+               self.fw.write_int(100)                  # database origin type
+               self.fw.pad(88)
+               try:
+                       self.fw.write_double(self.header.scene.properties['FLT']['origin lat']) #database origin lattitude
+               except:
+                       self.fw.write_double(0)
+               try:
+                       self.fw.write_double(self.header.scene.properties['FLT']['origin lon']) #database origin longitude
+               except:
+                       self.fw.write_double(0)
+               self.fw.pad(32)
                self.fw.write_int(0)            # ellipsoid model, 0 = WSG 1984
+               
                self.fw.pad(52)
 
        def write_vert_pal(self):
@@ -579,14 +1106,13 @@ class Database(Node):
                self.fw.write_short(67)                             # Vertex palette opcode.
                self.fw.write_short(8)                              # Length of record
                self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything.
-
                # Write records for individual vertices.
                for i in xrange(self.GRR.vertex_count()):
                        desc = self.GRR.request_vertex_desc(i)
                        self.fw.write_short(70)                         # Vertex with color normal and uv opcode.
                        self.fw.write_ushort(64)                        # Length of record
-                       self.fw.write_ushort(0)                         # Color name index
-                       self.fw.write_short(0x2000)                     # Flags set to no color
+                       self.fw.write_ushort(0)                                                 # Color name index
+                       self.fw.write_short(0x20000000)                                 # Flags
                        self.fw.write_double(desc.x)
                        self.fw.write_double(desc.y)
                        self.fw.write_double(desc.z)
@@ -595,16 +1121,19 @@ class Database(Node):
                        self.fw.write_float(desc.nz)
                        self.fw.write_float(desc.u)
                        self.fw.write_float(desc.v)
-                       self.fw.pad(12)
+                       self.fw.pad(4)
+                       self.fw.write_uint(desc.cindex)
+                       self.fw.pad(4)
 
        def write_tex_pal(self):
                if options.verbose >= 2:
                        print 'Writing texture palette.'
                # Write record for texture palette
-               for i in xrange(self.GRR.texture_count()):
+               for i, img in enumerate(self.GRR.texture_lst):
+                       filename = tex_files[img.name]
                        self.fw.write_short(64)                                         # Texture palette opcode.
                        self.fw.write_short(216)                                        # Length of record
-                       self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename
+                       self.fw.write_string(filename, 200) # Filename
                        self.fw.write_int(i)                                            # Texture index
                        self.fw.write_int(0)                                            # X
                        self.fw.write_int(0)                                            # Y
@@ -641,13 +1170,17 @@ class Database(Node):
                self.fw.write_short(32)                     # Color palette opcode.
                self.fw.write_short(4228)                   # Length of record
                self.fw.pad(128)
-               count = self.GRR.color_count()
+               try:
+                       cpalette = self.scene.properties['FLT']['Color Palette']
+               except:
+                       cpalette = defaultp.pal
+               count = len(cpalette)
                for i in xrange(count):
-                       col = self.GRR.request_max_color(i)
-                       self.fw.write_uchar(255)                  # alpha
-                       self.fw.write_uchar(col[2])               # b
-                       self.fw.write_uchar(col[1])               # g
-                       self.fw.write_uchar(col[0])               # r
+                       color = struct.unpack('>BBBB',struct.pack('>I',cpalette[i]))
+                       self.fw.write_uchar(color[3])               # alpha
+                       self.fw.write_uchar(color[2])               # b
+                       self.fw.write_uchar(color[1])               # g
+                       self.fw.write_uchar(color[0])               # r
                self.fw.pad(max(4096-count*4, 0))
 
        def write(self):
@@ -657,66 +1190,429 @@ class Database(Node):
                self.write_mat_pal()
                self.write_col_pal()
 
-               # Wrap everything in a group if it has an object child.
-               if self.has_object_child:
-                       self.header.fw.write_short(2)          # Group opcode
-                       self.header.fw.write_ushort(44)        # Length of record
-                       self.header.fw.write_string('g1', 8)   # ASCII ID
-                       self.header.fw.pad(32)
-               
                self.write_push()
-
-               for child in self.children:
-                       child.write()
-
+               
+               if options.flattenmesh:
+                       self.mnodes.reverse()
+                       for mnode in self.mnodes:
+                               mnode.write_faces()
+               else:
+                       for child in self.children:
+                               child.write()
                self.write_pop()
+       
+       def export_textures(self,texturepath):
+               for i in xrange(self.GRR.texture_count()):
+                       texture = self.GRR.texture_lst[i]
+                       
+                       if options.copy_textures:
+                               filename = os.path.normpath(os.path.join(options.texturespath, os.path.basename(self.GRR.request_texture_filename(i))))
+                       else:
+                               filename = os.path.normpath(self.GRR.request_texture_filename(i))
+                       
+                       tex_files[texture.name] = filename
 
+       def blender_export(self):
+               Node.blender_export(self)
+               self.export_textures(self)
+               return self.xrefnames
        def __init__(self, scene, fw):
                self.fw = fw
+               self.opcode = 1
+               self.childtypes = [73,14,2,63]
                self.scene = scene
-               self.all_objects = list(scene.objects)
-               self.GRR = GlobalResourceRepository()
+               self.childhash = dict()
+               self.parenthash = dict()
+               self.child_objects = list()
+               self.mnodes = list()
+               self.xrefnames = list()
+               for i in self.scene.objects:
+                       self.parenthash[i.name] = list()
+                       self.childhash[i.name] = False
+               for i in self.scene.objects:
+                       if i.parent:
+                               self.childhash[i.parent.name] = True
+                               self.parenthash[i.parent.name].append(i)
+                       else:
+                               self.child_objects.append(i)
 
-               Node.__init__(self, None, self, None, self.all_objects)
+               self.GRR = GlobalResourceRepository()
+               Node.__init__(self, None, self, None,None)
 
-def fs_callback(filename):
-       Blender.Window.WaitCursor(True)
-       
-       if Blender.sys.exists(filename):
-               r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No')
-               if r != 1:
-                       if options.verbose >= 1:
-                               print 'Export cancelled.'
-                       return
-       
-       time1 = Blender.sys.time() # Start timing
+def write_attribute_files():
+       for imgname in tex_files:
+               blentex = Blender.Image.Get(imgname)
+               exportdict = FLT_Records['Image'].copy()
+               
+               if blentex.properties.has_key('FLT'):
+                       for key in exportdict.keys():
+                               if blentex.properties.has_key(key):
+                                       exportdict[key] = blentex.properties['FLT'][key]
+               
+               # ClampX/Y override
+               if blentex.clampX:
+                       exportdict['11i!WrapU'] = 1
+               if blentex.clampY:
+                       exportdict['12i!WrapV'] = 1 
+               
+               exportdict['16i!Enviorment'] = 0 
+               
+               # File type
+               typecode = 0
+               try:
+                       typestring = os.path.splitext(blentex.getFilename())[1]
+                       
+                       if typestring == '.rgba':
+                               typecode = 5
+                       elif typestring == '.rgb':
+                               typecode = 4
+                       elif typestring == '.inta':
+                               typecode = 3
+                       elif typestring == '.int':
+                               typecode = 2
+               except:
+                       pass
+               
+               exportdict['7i!File Format'] = typecode
+
+               fw = FltOut(tex_files[imgname] + '.attr')
+               size = blentex.getSize()
+               fw.write_int(size[0])
+               fw.write_int(size[1])
+               for key in records['Image']:
+                       (type,length,propname) = records['Image'][key]
+                       write_prop(fw,type,exportdict[propname],length)
+               fw.close_file()
+
+#globals used by the scene export function
+exportlevel = None
+xrefsdone = None
+
+def dbexport_internal(scene):
+       global exportlevel
+       global xrefsdone
+       global options
+
+       if exportlevel == 0 or not options.externalspath:
+               fname = os.path.join(options.basepath,scene.name + '.flt')
+       else:
+               fname = os.path.join(options.externalspath,scene.name + '.flt')
        
-       fw = FltOut(filename)
-
-       db = Database(Blender.Scene.GetCurrent(), fw)
+       fw = FltOut(fname)
+       db = Database(scene,fw)
        
        if options.verbose >= 1:
-               print 'Pass 1: Exporting from Blender.\n'
-       
-       db.blender_export()
+               print 'Pass 1: Exporting ', scene.name,'.flt from Blender.\n'
        
+       xreflist = db.blender_export()
        if options.verbose >= 1:
-               print 'Pass 2: Writing %s\n' % filename
-               
+               print 'Pass 2: Writing %s\n' % fname
        db.write()
-
        fw.close_file()
+       
+       if options.doxrefs:
+               for xname in xreflist:
+                       try:
+                               xrefscene = Blender.Scene.Get(xname)
+                       except:
+                               xrefscene = None
+                       if xrefscene and xname not in xrefsdone:
+                               xrefsdone.append(xname)
+                               exportlevel+=1
+                               dbexport_internal(xrefscene)
+                               exportlevel-=1
+       return fname
+#main database export function
+def dbexport():
+       global exportlevel
+       global xrefsdone
+       exportlevel = 0
+       xrefsdone = list()
+       
+       Blender.Window.WaitCursor(True)
+       time1 = Blender.sys.time() # Start timing
+       
        if options.verbose >= 1:
+               print '\nOpenFlight Exporter'
+               print 'Version:', __version__
+               print 'Author: Greg MacDonald, Geoffrey Bantle'
+               print __url__[2]
+               print
+       
+       fname = dbexport_internal(Blender.Scene.GetCurrent())
+       if options.verbose >=1:
                print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1)
-               
        Blender.Window.WaitCursor(False)
+       
+       #optional: Copy textures
+       if options.copy_textures:
+               for imgname in tex_files:
+                       #Check to see if texture exists in target directory
+                       if not os.path.exists(tex_files[imgname]):
+                               #Get original Blender file name
+                               origpath = Blender.sys.expandpath(Blender.Image.Get(imgname).getFilename())
+                               #copy original to new
+                               if os.path.exists(origpath):
+                                       shutil.copyfile(origpath,tex_files[imgname])
+       
+       #optional: Write attribute files
+       if options.write_attrib_files:
+               write_attribute_files()
+
+       if options.xapp:
+               cmd= options.xappath + " " + fname 
+               status = os.system(cmd)
+       
+
+#Begin UI code
+FLTExport = None
+FLTClose = None
+FLTLabel = None
+
+FLTBaseLabel = None
+FLTTextureLabel = None
+FLTXRefLabel = None
+
+FLTBaseString = None
+FLTTextureString = None
+FLTXRefString = None
+
+FLTBasePath = None
+FLTTexturePath = None
+FLTXRefPath = None
+
+FLTShadeExport = None
+FLTShadeDefault = None
+
+FLTCopyTex = None
+FLTDoXRef = None
+FLTGlobal = None
+
+FLTScale = None
+
+FLTXAPP = None
+FLTXAPPath = None
+FLTXAPPString = None
+FLTXAPPLabel = None
+FLTXAPPChooser = None
+
+FLTAttrib = None
+
+def setshadingangle(ID,val):
+       global options
+       options.shading_default = val
+def setBpath(fname):
+       global options
+       options.basepath = os.path.dirname(fname)
+       #update xref and textures path too....
+       if(os.path.exists(os.path.join(options.basepath,'externals'))):
+               options.externalspath = os.path.join(options.basepath,'externals')
+       if(os.path.exists(os.path.join(options.texturespath,'textures'))):
+               options.texturespath = os.path.join(options.basepath,'textures')
+def setexportscale(ID,val):
+       global options
+       options.scale = val
+
+def setTpath(fname):
+       global options
+       options.texturespath = os.path.dirname(fname)
+def setXpath(fname):
+       global options
+       options.externalspath = os.path.dirname(fname)
+def setXApath(fname):
+       global options
+       options.xappath = fname
+       d = dict()
+       d['xappath'] = options.xappath
+       Blender.Registry.SetKey('flt_export', d, 1) 
+def event(evt, val):
+       x = 1
+def but_event(evt):
+       global options
+       
+       global FLTExport
+       global FLTClose 
+       global FLTLabel
+       
+       global FLTBaseLabel
+       global FLTTextureLabel
+       global FLTXRefLabel
+
+       global FLTBaseString
+       global FLTTextureString
+       global FLTXRefString
+       
+       global FLTBasePath
+       global FLTTexturePath
+       global FLTXRefPath
+       
+       global FLTShadeExport
+       global FLTShadeDefault
+       
+       global FLTCopyTex
+       global FLTDoXRef
+       global FLTGlobal
+       
+       global FLTScale
+       
+       
+       global FLTXAPP
+       global FLTXAPPath
+       global FLTXAPPString
+       global FLTXAPPLabel     
+       global FLTXAPPChooser
+
+       global FLTAttrib
+       
+       
+       
+       #choose base path for export
+       if evt == 4:
+               Blender.Window.FileSelector(setBpath, "DB Root", options.basepath)
+               
+       #choose XREF path
+       if evt == 6:
+               Blender.Window.FileSelector(setXpath,"DB Externals",options.externalspath)
+
+       #choose texture path
+       if evt == 8:
+               Blender.Window.FileSelector(setTpath,"DB Textures",options.texturespath)
+
+       #export shading toggle
+       if evt == 9:
+               options.export_shading = FLTShadeExport.val
+       #export Textures
+       if evt == 11:
+               options.copy_textures = FLTCopyTex.val
+       #export XRefs
+       if evt == 13:
+               options.doxrefs = FLTDoXRef.val
+       #export Transforms
+       if evt == 12:
+               options.export_transform = FLTGlobal.val
+               
+       if evt == 14:
+               options.xapp = FLTXAPP.val
+       if evt == 16:
+               Blender.Window.FileSelector(setXApath,"External Application",options.xappath)
+       if evt == 20:
+               options.write_attrib_files = FLTAttrib.val
+       
+       #Export DB
+       if evt == 1:
+               dbexport()
+       
+       #exit
+       if evt == 2:
+               Draw.Exit()
+
+from Blender.BGL import *
+from Blender import Draw
+def gui():
+       
+       global options
+       
+       global FLTExport
+       global FLTClose 
+       global FLTLabel
+       
+       global FLTBaseLabel
+       global FLTTextureLabel
+       global FLTXRefLabel
+
+       global FLTBaseString
+       global FLTTextureString
+       global FLTXRefString
+       
+       global FLTBasePath
+       global FLTTexturePath
+       global FLTXRefPath
+       
+       global FLTShadeExport
+       global FLTShadeDefault
+       
+       global FLTCopyTex
+       global FLTDoXRef
+       global FLTGlobal
+       
+       global FLTScale
+       
+       global FLTXAPP
+       global FLTXAPPath
+       global FLTXAPPString
+       global FLTXAPPLabel
+       global FLTXAPPChooser   
+       
+       global FLTAttrib
+       
+       glClearColor(0.880,0.890,0.730,1.0 )
+       glClear(GL_COLOR_BUFFER_BIT)
+       
+       areas = Blender.Window.GetScreenInfo()
+       curarea = Blender.Window.GetAreaID()
+       curRect = None
+       
+       for area in areas:
+               if area['id'] == curarea:
+                       curRect = area['vertices']
+                       break
+       
+       width = curRect[2] - curRect[0]
+       height = curRect[3] - curRect[1]
+       #draw from top to bottom....
+       cx = 50
+       #Draw Title Bar...
+       #glRasterPos2d(cx, curRect[3]-100)
+       #FLTLabel = Draw.Text("FLT Exporter V2.0",'large')
+       cy = height - 80
+       
+       #base path
+       FLTBaseLabel = Draw.Label("Base Path:",cx,cy,100,20)
+       FLTBaseString = Draw.String("",3,cx+100,cy,300,20,options.basepath,255,"Folder to export to")
+       FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder")
+       
+       cy = cy-40
+       
+       #externals path
+       FLTXRefLabel = Draw.Label("XRefs:",cx,cy,100,20)
+       FLTXRefString = Draw.String("",5,cx+100,cy,300,20,options.externalspath,255,"Folder for external references")
+       FLTXRefChooser = Draw.PushButton("...",6,cx+400,cy,20,20,"Choose Folder")
+       cy = cy-40
+       #Textures path
+       FLTTextureLabel = Draw.Label("Textures:",cx,cy,100,20)
+       FLTTextureString = Draw.String("",7,cx+100,cy,300,20,options.texturespath,255,"Folder for texture files")
+       FLTTextureChooser = Draw.PushButton("...",8,cx+400,cy,20,20,"Choose Folder")
+       cy=cy-40
+       #External application path
+       FLTXAPPLabel = Draw.Label("XApp:",cx,cy,100,20)
+       FLTXAPPString = Draw.String("",15,cx+100,cy,300,20,options.xappath,255,"External application to launch when done")
+       FLTXAPPChooser = Draw.PushButton("...",16,cx+400, cy,20,20,"Choose Folder")
+       
+       cy = cy-60
+       #Shading Options
+       FLTShadeExport = Draw.Toggle("Default Shading",9,cx,cy,100,20,options.export_shading,"Turn on export of custom shading")
+       FLTShadDefault = Draw.Number("",10,cx + 120,cy,100,20,options.shading_default,0.0,180.0,"Default shading angle for objects with no custom shading assigned",setshadingangle)
+       
+       cy = cy-40
+       FLTScale = Draw.Number("Export Scale",14,cx,cy,220,20,options.scale,0.0,100.0,"Export scaling factor",setexportscale)
+       
+       cy = cy-40
+       #misc Options
+       FLTCopyTex = Draw.Toggle("Copy Textures",11,cx,cy,220,20,options.copy_textures,"Copy textures to folder indicated above")
+       cy = cy-40
+       FLTGlobal = Draw.Toggle("Export Transforms",12,cx,cy,220,20,options.export_transform,"If unchecked, Global coordinates are used (recommended)")
+       cy = cy-40
+       FLTDoXRef = Draw.Toggle("Export XRefs", 13,cx,cy,220,20,options.doxrefs,"Export External references (only those below current scene!)")
+       cy = cy-40
+       FLTXAPP = Draw.Toggle("Launch External App", 14, cx,cy,220,20,options.xapp,"Launch External Application on export")
+       cy = cy-40
+       FLTAttrib = Draw.Toggle("Write Attribute Files", 20, cx, cy, 220,20,options.write_attrib_files, "Write Texture Attribute files")
+       #FLTXAPPATH = Draw.String("",15,cx,cy,300,20,options.xappath,255,"External application path")
+       
 
-if options.verbose >= 1:
-       print '\nOpenFlight Exporter'
-       print 'Version:', __version__
-       print 'Author: Greg MacDonald'
-       print __url__[2]
-       print
+       #Draw export/close buttons
+       FLTExport = Draw.PushButton("Export",1,cx,20,100,20,"Export to FLT")
+       FLTClose = Draw.PushButton("Close", 2, cx+120,20,100,20,"Close window")
        
-fname = Blender.sys.makename(ext=".flt")
-Blender.Window.FileSelector(fs_callback, "Export OpenFlight v16.0", fname)
+
+Draw.Register(gui,event,but_event)
\ No newline at end of file
index 442c9728e911fa838eebdf35d7cd499493d33d50..4a9b86c45d242441c3a6c6b0bc0929880c707ad8 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+__bpydoc__ ="""\
+File read/write module used by OpenFlight I/O and tool scripts. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+"""
+
 import Blender
 from struct import *
 import re
@@ -199,7 +204,9 @@ class FltOut:
         self.file.close()
 
     def __init__(self, filename):
-        self.file = open(filename, 'wb')
+               self.file = open(filename, 'wb')
+               self.filename = filename
+               
 
 class FileFinder:
     def add_file_to_search_path(self, filename):
index ca0db650447d0c684ce60bde59a6b5f851d88aa6..220fc9f355c2439044f632a63057964314275b92 100644 (file)
@@ -1,72 +1,26 @@
 #!BPY
 """ Registration info for Blender menus:
 Name: 'OpenFlight (.flt)...'
-Blender: 238
+Blender: 245
 Group: 'Import'
 Tip: 'Import OpenFlight (.flt)'
 """
 
-__author__ = "Greg MacDonald, Campbell Barton"
-__version__ = "1.2 10/20/05"
+__author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle"
+__version__ = "2.0 11/21/07"
 __url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
 __bpydoc__ = """\
 This script imports OpenFlight files into Blender. OpenFlight is a
 registered trademark of MultiGen-Paradigm, Inc.
 
-Run from "File->Import" menu.
-
-Options are available from Blender's "Scripts Config Editor," accessible through
-the "Scripts->System" menu from the scripts window.
-
-All global_prefs are toggle switches that let the user choose what is imported. Most
-are straight-forward, but one option could be a source of confusion. The 
-"Diffuse Color From Face" option when set pulls the diffuse color from the face
-colors. Otherwise the diffuse color comes from the material. What may be
-confusing is that this global_prefs only works if the "Diffuse Color" option is set.
-
-New Features:<br>
-* Importer is 14 times faster.<br>
-* External triangle module is no longer required, but make sure the importer
-has a 3d View screen open while its running or triangulation won't work.<br>
-* Should be able to import all versions of flight files.
-
-Features:<br>
-* Heirarchy retained.<br>
-* First texture imported.<br>
-* Colors imported from face or material.<br>
-* LOD seperated out into different layers.<br>
-* Asks for location of unfound textures or external references.<br>
-* Searches Blender's texture directory in the user preferences panel.<br>
-* Triangles with more than 4 verts are triangulated if the Triangle python
-module is installed.<br>
-* Matrix transforms imported.<br>
-* External references to whole files are imported.
-
-Things To Be Aware Of:<br>
-* Each new color and face attribute creates a new material and there are only a maximum of 16
-materials per object.<br>
-* For triangulated faces, normals must be recomputed outward manually by typing
-CTRL+N in edit mode.<br>
-* You can change global_prefs only after an initial import.<br>
-* External references are imported as geometry and will be exported that way.<br>
-* A work around for not using the Triangle python module is to simply to 
-triangulate in Creator before importing. This is only necessary if your
-model contains 5 or more vertices.<br>
-* You have to manually blend the material color with the texture color.
-
-What's Not Handled:<br>
-* Special texture repeating modes.<br>
-* Replications and instancing.<br>
-* Comment and attribute fields.<br>
-* Light points.<br>
-* Animations.<br>
-* External references to a node within a file.<br>
-* Multitexturing.<br>
-* Vetex colors.<br>
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_flt
+
+Note: This file is a grab-bag of old and new code. It needs some cleanup still.
 """
 
 # flt_import.py is an OpenFlight importer for blender.
-# Copyright (C) 2005 Greg MacDonald
+# Copyright (C) 2005 Greg MacDonald, 2007  Blender Foundation
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -87,15 +41,33 @@ import os
 import BPyMesh
 import BPyImage
 import flt_filewalker 
+import flt_properties
+reload(flt_properties)
+from flt_properties import *
 
-Vector= Blender.Mathutils.Vector
+#Globals. Should Clean these up and minimize their usage.
 
-def col_to_gray(c):
-       return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
+typecodes = ['c','C','s','S','i','I','f','d','t']
+records = dict()
+
+FLTBaseLabel = None
+FLTBaseString = None
+FLTBaseChooser = None
+FLTExport = None
+FLTClose = None
+FLTDoXRef = None
+FLTScale = None
+FLTShadeImport = None
+FLTAttrib = None
+
+Vector= Blender.Mathutils.Vector
+FLOAT_TOLERANCE = 0.01
 
+FF = flt_filewalker.FileFinder()
+current_layer = 0x01
 
 global_prefs = dict()
-global_prefs['verbose']= 1
+global_prefs['verbose']= 4
 global_prefs['get_texture'] = True
 global_prefs['get_diffuse'] = True
 global_prefs['get_specular'] = False
@@ -105,8 +77,41 @@ global_prefs['get_ambient'] = False
 global_prefs['get_shininess'] = True
 global_prefs['color_from_face'] = True
 global_prefs['fltfile']= ''
+global_prefs['smoothshading'] = 1
+global_prefs['doxrefs'] = 1
+global_prefs['scale'] = 1.0
+global_prefs['attrib'] = 0
 msg_once = False
 
+throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent.
+do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
+
+#Process FLT record definitions
+for record in FLT_Records:
+       props = dict()
+       for prop in FLT_Records[record]:
+               position = ''
+               slice = 0
+               (format,name) = prop.split('!')
+               for i in format:
+                       if i not in typecodes:
+                               position = position + i
+                               slice = slice + 1
+                       else:
+                               break
+               type = format[slice:]
+               length = type[1:] 
+               if len(length) == 0:
+                       length = 1
+               else:
+                       type = type[0]
+                       length = int(length)
+               
+               props[int(position)] = (type,length,prop)
+       records[record] = props
+
+def col_to_gray(c):
+       return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
 class MaterialDesc:
        # Was going to use int(f*1000.0) instead of round(f,3), but for some reason
        # round produces better results, as in less dups.
@@ -185,16 +190,14 @@ class VertexDesc:
                self.y = 0.0
                self.z = 0.0
                
-               ''' # IGNORE_NORMALS
+               
                self.nx = 0.0
-               self.ny = 1.0
+               self.ny = 0.0
                self.nz = 0.0
-               '''
+               
                self.uv= Vector(0,0)
-               self.r = 1.0
-               self.g = 1.0
-               self.b = 1.0
-               self.a = 1.0        
+               self.cindex = 127 #default/lowest
+               self.cnorm = False        
 
 class LightPointAppDesc:
        def make_key(self):
@@ -222,7 +225,7 @@ class LightPointAppDesc:
                self.props.update({'LOD scale': 0.0})
 
 class GlobalResourceRepository:
-       def request_lightpoint_app(self, desc):
+       def request_lightpoint_app(self, desc, scene):
                match = self.light_point_app.get(desc.make_key())
                
                if match:
@@ -231,7 +234,7 @@ class GlobalResourceRepository:
                        # Create empty and fill with properties.
                        name = desc.props['type'] + ': ' + desc.props['id']
                        object = Blender.Object.New('Empty', name)
-                       scene.link(object)
+                       scene.objects.link(object)
                        object.Layers= current_layer
                        object.sel= 1
                        
@@ -306,6 +309,9 @@ class GlobalResourceRepository:
                return tex
                
        def __init__(self):
+               
+               #list of scenes xrefs belong to.
+               self.xrefs = dict()
                # material
                self.mat_dict = dict()
                mat_lst = Blender.Material.Get()
@@ -341,108 +347,6 @@ class GlobalResourceRepository:
                # light point
                self.light_point_app = dict()
                
-# Globals
-GRR = GlobalResourceRepository()
-FF = flt_filewalker.FileFinder()
-scene = Blender.Scene.GetCurrent() # just hope they dont chenge scenes once the file selector pops up.
-current_layer = 0x01
-
-
-# Opcodes that indicate its time to return control to parent.
-throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63]
-do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
-
-opcode_name = { 0: 'db',
-                               1: 'head',
-                               2: 'grp',
-                               4: 'obj',
-                               5: 'face',
-                               10: 'push',
-                               11: 'pop',
-                               14: 'dof',
-                               19: 'push sub',
-                               20: 'pop sub',
-                               21: 'push ext',
-                               22: 'pop ext',
-                               23: 'cont',
-                               31: 'comment',
-                               32: 'color pal',
-                               33: 'long id',
-                               49: 'matrix',
-                               50: 'vector',
-                               52: 'multi-tex',
-                               53: 'uv lst',
-                               55: 'bsp',
-                               60: 'rep',
-                               61: 'inst ref',
-                               62: 'inst def',
-                               63: 'ext ref',
-                               64: 'tex pal',
-                               67: 'vert pal',
-                               68: 'vert w col',
-                               69: 'vert w col & norm',
-                               70: 'vert w col, norm & uv',
-                               71: 'vert w col & uv',
-                               72: 'vert lst',
-                               73: 'lod',
-                               74: 'bndin box',
-                               76: 'rot edge',
-                               78: 'trans',
-                               79: 'scl',
-                               80: 'rot pnt',
-                               81: 'rot and/or scale pnt',
-                               82: 'put',
-                               83: 'eyepoint & trackplane pal',
-                               84: 'mesh',
-                               85: 'local vert pool',
-                               86: 'mesh prim',
-                               87: 'road seg',
-                               88: 'road zone',
-                               89: 'morph vert lst',
-                               90: 'link pal',
-                               91: 'snd',
-                               92: 'rd path',
-                               93: 'snd pal',
-                               94: 'gen matrix',
-                               95: 'txt',
-                               96: 'sw',
-                               97: 'line styl pal',
-                               98: 'clip reg',
-                               100: 'ext',
-                               101: 'light src',
-                               102: 'light src pal',
-                               103: 'reserved',
-                               104: 'reserved',
-                               105: 'bndin sph',
-                               106: 'bndin cyl',
-                               107: 'bndin hull',
-                               108: 'bndin vol cntr',
-                               109: 'bndin vol orient',
-                               110: 'rsrvd',
-                               111: 'light pnt',
-                               112: 'tex map pal',
-                               113: 'mat pal',
-                               114: 'name tab',
-                               115: 'cat',
-                               116: 'cat dat',
-                               117: 'rsrvd',
-                               118: 'rsrvd',
-                               119: 'bounding hist',
-                               120: 'rsrvd',
-                               121: 'rsrvd',
-                               122: 'push attrib',
-                               123: 'pop attrib',
-                               124: 'rsrvd',
-                               125: 'rsrvd',
-                               126: 'curv',
-                               127: 'road const',
-                               128: 'light pnt appear pal',
-                               129: 'light pnt anim pal',
-                               130: 'indexed lp',
-                               131: 'lp sys',
-                               132: 'indx str',
-                               133: 'shdr pal'}
-
 class Handler:
        def in_throw_back_lst(self, opcode):
                return opcode in self.throw_back_lst
@@ -487,11 +391,11 @@ class Node:
                        print '-', self.props['comment'],
 
                        print
-
+                
                for child in self.children:
                        child.blender_import()
-               
-               # Import comment.
+                       
+# Import comment.
 #        if self.props['comment'] != '':
 #            name = 'COMMENT: ' + self.props['id']
 #            t = Blender.Text.New(name)
@@ -568,8 +472,8 @@ class Node:
                                else:
                                        if global_prefs['verbose'] >= 3:
                                                print p + ' ignored'
-                                       elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:
-                                               print opcode_name[opcode], 'not handled'                        
+                                       elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:   
+                                               print 'not handled'
                                        
        def get_level(self):
                return self.level
@@ -581,7 +485,19 @@ class Node:
        def parse_comment(self):
                self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4)
                return True
-
+       
+       def parse_record(self):
+               self.props['type'] = self.opcode
+               props = records[self.opcode]
+               propkeys = props.keys()
+               propkeys.sort()
+               for position in propkeys:
+                       (type,length,name) = props[position]
+                       self.props[name] = read_prop(self.header.fw,type,length)
+               try: #remove me!
+                       self.props['id'] = self.props['3t8!id']
+               except:
+                       pass
        def __init__(self, parent, header):
                self.root_handler = Handler()
                self.child_handler = Handler()
@@ -647,20 +563,16 @@ class VertexPalette(Node):
                return v
 
        def parse_vertex_post_common(self, v):
-               if not v.flags & 0x2000: # 0x2000 = no color
-                       if v.flags & 0x1000: # 0x1000 = packed color
-                               v.a = self.header.fw.read_uchar()
-                               v.b = self.header.fw.read_uchar()
-                               v.g = self.header.fw.read_uchar()
-                               v.r = self.header.fw.read_uchar()
-                       else:
-                               self.header.fw.read_ahead(4)
-                       
-                       color_index = self.header.fw.read_uint()
-                       v.r, v.g, v.b, v.a= self.header.get_color(color_index)
-               
+               #if not v.flags & 0x2000: # 0x2000 = no color
+                       #if v.flags & 0x1000: # 0x1000 = packed color
+                       #       v.a = self.header.fw.read_uchar()
+                       #       v.b = self.header.fw.read_uchar()
+                       #       v.g = self.header.fw.read_uchar()
+                       #       v.r = self.header.fw.read_uchar()
+                       #else:
+               self.header.fw.read_ahead(4) #skip packed color
+               v.cindex = self.header.fw.read_uint()
                self.vert_desc_lst.append(v)
-               
                return True
 
        def parse_vertex_c(self):
@@ -672,16 +584,10 @@ class VertexPalette(Node):
 
        def parse_vertex_cn(self):
                v = self.parse_vertex_common()
-               
-               '''
+               v.cnorm = True
                v.nx = self.header.fw.read_float()
                v.ny = self.header.fw.read_float()
                v.nz = self.header.fw.read_float()
-               '''
-               # Just to advance
-               self.header.fw.read_float()
-               self.header.fw.read_float()
-               self.header.fw.read_float()
                
                self.parse_vertex_post_common(v)
                
@@ -698,15 +604,10 @@ class VertexPalette(Node):
 
        def parse_vertex_cnuv(self):
                v = self.parse_vertex_common()
-               '''
+               v.cnorm = True
                v.nx = self.header.fw.read_float()
                v.ny = self.header.fw.read_float()
                v.nz = self.header.fw.read_float()
-               '''
-               # Just to advance
-               self.header.fw.read_float()
-               self.header.fw.read_float()
-               self.header.fw.read_float()
                
                v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
 
@@ -721,89 +622,370 @@ class InterNode(Node):
        def __init__(self):
                self.object = None
                self.mesh = None
-               self.isMesh = False
+               self.hasMesh = False
                self.faceLs= []
                self.matrix = None
-       
-       def blender_import_my_faces(self):
+               self.vis = True
+               self.hasmtex = False
+               self.uvlayers = dict()
+               self.blayernames = dict()
+               self.subfacelevel = 0
+               
+               mask = 2147483648
+               for i in xrange(7):
+                       self.uvlayers[mask] = False
+                       mask = mask / 2
                
+
+       def blender_import_my_faces(self):
+
                # Add the verts onto the mesh
-               mesh = self.mesh
                blender_verts= self.header.vert_pal.blender_verts
                vert_desc_lst= self.header.vert_pal.vert_desc_lst
                
-               vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices]
-               
-               mesh.verts.extend([blender_verts[i] for i in vert_list])
-               
+               vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing?
+               face_edges= []
+               face_verts= []
+               self.mesh.verts.extend([blender_verts[i] for i in vert_list])
                
                new_faces= []
                new_faces_props= []
                ngon= BPyMesh.ngon
                vert_index= 1
+               
+               #add vertex color layer for baked face colors.
+               self.mesh.addColorLayer("FLT_Fcol")
+               self.mesh.activeColorLayer = "FLT_Fcol"
+               
+               FLT_OrigIndex = 0
                for flt_face in self.faceLs:
-                       material_index= flt_face.blen_mat_idx
-                       image= flt_face.blen_image
-                       
+                       if flt_face.tex_index != -1:
+                               try:
+                                       image= self.header.tex_pal[flt_face.tex_index][1]
+                               except KeyError:
+                                       image= None
+                       else:
+                               image= None
                        face_len= len(flt_face.indices)
                        
+                       #create dummy uvert dicts
+                       if len(flt_face.uverts) == 0:
+                               for i in xrange(face_len):
+                                       flt_face.uverts.append(dict())
+                       #May need to patch up MTex info
+                       if self.hasmtex:
+                               #For every layer in mesh, there should be corresponding layer in the face
+                               for mask in self.uvlayers.keys():
+                                       if self.uvlayers[mask]:
+                                               if not flt_face.uvlayers.has_key(mask): #Does the face have this layer?
+                                                       #Create Layer info for this face
+                                                       flt_face.uvlayers[mask] = dict()
+                                                       flt_face.uvlayers[mask]['texture index'] = -1
+                                                       flt_face.uvlayers[mask]['texture enviorment'] = 3
+                                                       flt_face.uvlayers[mask]['texture mapping'] = 0
+                                                       flt_face.uvlayers[mask]['texture data'] = 0
+                                                       
+                                                       #now go through and create dummy uvs for this layer
+                                                       for uvert in flt_face.uverts:
+                                                                       uv = Vector(0.0,0.0)
+                                                                       uvert[mask] = uv
+
                        # Get the indicies in reference to the mesh.
-                       
                        uvs= [vert_desc_lst[j].uv for j in flt_face.indices]
-                       if face_len <=4: # tri or quad
+                       if face_len == 1:
+                               pass
+                       elif face_len == 2:
+                               face_edges.append((vert_index, vert_index+1))
+                       elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3:
+                               i = 0
+                               while i < (face_len-1):
+                                       face_edges.append((vert_index + i, vert_index + i + 1))
+                                       i = i + 1
+                               if flt_face.props['draw type'] == 2:
+                                       face_edges.append((vert_index + i,vert_index)) 
+                       elif face_len == 3 or face_len == 4: # tri or quad
+                               #if face_len == 1:
+                               #       pass
+                               #if face_len == 2:
+                               #       face_edges.append((vert_index, vert_index+1))
                                new_faces.append( [i+vert_index for i in xrange(face_len)] )
-                               new_faces_props.append((material_index, image, uvs))
+                               new_faces_props.append((None, image, uvs, flt_face.uverts, flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,0, flt_face.subfacelevel))
                        
                        else: # fgon
                                mesh_face_indicies = [i+vert_index for i in xrange(face_len)]
-                               tri_ngons= ngon(mesh, mesh_face_indicies)
+                               tri_ngons= ngon(self.mesh, mesh_face_indicies)
                                new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons])
-                               new_faces_props.extend( [ (material_index, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]) ) for tri in tri_ngons ] )
+                               new_faces_props.extend( [ (None, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]), [flt_face.uverts[tri[0]], flt_face.uverts[tri[1]], flt_face.uverts[tri[2]]], flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,1, flt_face.subfacelevel) for tri in tri_ngons ])
                        
                        vert_index+= face_len
-               
-               mesh.faces.extend(new_faces)
-               
-               try:    mesh.faceUV= True
-               except: pass
-               
-               for i, f in enumerate(mesh.faces):
-                       f.mat, f.image, f.uv= new_faces_props[i]
-       
+                       FLT_OrigIndex+=1
+               
+               self.mesh.faces.extend(new_faces)
+               self.mesh.edges.extend(face_edges)
+               
+               #add in the FLT_ORIGINDEX layer
+               if len(self.mesh.faces):
+                       try:    self.mesh.faceUV= True
+                       except: pass
+               
+                       if self.mesh.faceUV == True:
+                               self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0')
+               
+                       #create name layer for faces
+                       self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"])
+                       #create layer for face color indices
+                       self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
+                       #create index layer for faces. This is needed by both FGONs and subfaces
+                       self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
+                       #create temporary FGON flag layer. Delete after remove doubles
+                       self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"])
+                       self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"])
+                       
+                       for i, f in enumerate(self.mesh.faces):
+                               f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] #fix this!
+                               f.mode |= Blender.Mesh.FaceModes["LIGHT"]
+                               props = new_faces_props[i]
+                               #f.mat = props[0]
+                               f.image = props[1]
+                               f.uv = props[2]
+                               #set vertex colors
+                               color = self.header.get_color(props[5])
+                               if not color:
+                                       color = [255,255,255,255]
+                               for mcol in f.col:
+                                       mcol.a = color[3]
+                                       mcol.r = color[0]
+                                       mcol.g = color[1]
+                                       mcol.b = color[2]
+                               
+                               f.setProperty("FLT_SFLEVEL", props[9])
+                               f.setProperty("FLT_ORIGINDEX",i)
+                               f.setProperty("FLT_ID",props[6]['id'])
+                               #if props[5] > 13199:
+                               #       print "Warning, invalid color index read in! Using default!"
+                               #       f.setProperty("FLT_COL",127)
+                               #else:
+                               if(1):                  #uh oh....
+                                       value = struct.unpack('>i',struct.pack('>I',props[5]))[0]
+                                       f.setProperty("FLT_COL",value)
+                               
+                               #if props[8]: 
+                               #       f.setProperty("FLT_FGON",1)
+                               #else:
+                               #       f.setProperty("FLT_FGON",0)
+                       
+                       
+                       #Create multitex layers, if present.
+                       actuvlayer = self.mesh.activeUVLayer
+                       if(self.hasmtex):
+                               #For every multi-tex layer, we have to add a new UV layer to the mesh
+                               for i,mask in enumerate(reversed(sorted(self.uvlayers))):
+                                       if self.uvlayers[mask]:
+                                               self.blayernames[mask] = "Layer" + str(i+1)
+                                               self.mesh.addUVLayer(self.blayernames[mask])
+                               
+                               #Cycle through availible multi-tex layers and add face UVS
+                               for mask in self.uvlayers:
+                                       if self.uvlayers[mask]:
+                                               self.mesh.activeUVLayer = self.blayernames[mask]
+                                               for j, f in enumerate(self.mesh.faces):
+                                                       f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
+                                                       f.mode |= Blender.Mesh.FaceModes["LIGHT"]
+                                                       props = new_faces_props[j]
+                                                       uvlayers = props[4]
+                                                       if uvlayers.has_key(mask): #redundant
+                                                               uverts = props[3]
+                                                               for k, uv in enumerate(f.uv):
+                                                                       uv[0] = uverts[k][mask][0]
+                                                                       uv[1] = uverts[k][mask][1]
+                               
+                                                               uvlayer = uvlayers[mask]
+                                                               tex_index = uvlayer['texture index']
+                                                               if tex_index != -1:
+                                                                       try:
+                                                                               f.image = self.header.tex_pal[tex_index][1]
+                                                                       except KeyError:
+                                                                               f.image = None
+                                                                       
+                       if global_prefs['smoothshading'] == True and len(self.mesh.faces):
+                               #We need to store per-face vertex normals in the faces as UV layers and delete them later.
+                               self.mesh.addUVLayer("FLTNorm1")
+                               self.mesh.addUVLayer("FLTNorm2")
+                               self.mesh.activeUVLayer = "FLTNorm1"
+                               for f in self.mesh.faces:
+                                       f.smooth = 1
+                                       #grab the X and Y components of normal and store them in UV 
+                                       for i, uv in enumerate(f.uv):
+                                               vert = f.v[i].index
+                                               vert_desc = vert_desc_lst[vert_list[vert-1]]
+                                               if vert_desc.cnorm:
+                                                       uv[0] = vert_desc.nx
+                                                       uv[1] = vert_desc.ny
+                                               else:
+                                                       uv[0] = 0.0
+                                                       uv[1] = 0.0
+                               
+                               #Now go through and populate the second UV Layer with the z component
+                               self.mesh.activeUVLayer = "FLTNorm2"
+                               for f in self.mesh.faces:
+                                       for i, uv in enumerate(f.uv):
+                                               vert = f.v[i].index
+                                               vert_desc = vert_desc_lst[vert_list[vert-1]]
+                                               if vert_desc.cnorm:
+                                                       uv[0] = vert_desc.nz
+                                                       uv[1] = 0.0
+                                               else:
+                                                       uv[0] = 0.0
+                                                       uv[1] = 0.0
+                       
+                               
+                               
+                       #Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier.
+                       Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
+                       self.mesh.verts.delete(0) # remove the dummy vert
+                       self.mesh.sel= 1
+                       self.header.scene.update(1) #slow!
+                       self.mesh.remDoubles(0.0001)
+                       
+                       edgeHash = dict()
+
+                       for edge in self.mesh.edges:
+                               edgeHash[edge.key] = edge.index
+
+
+                       if global_prefs['smoothshading'] == True and len(self.mesh.faces):
+                               
+                               #rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way.
+                               facenorms = []
+                               self.mesh.activeUVLayer = "FLTNorm1"
+                               for face in self.mesh.faces:
+                                       facenorm = []
+                                       for uv in face.uv:
+                                               facenorm.append(Vector(uv[0],uv[1],0.0))
+                                       facenorms.append(facenorm)
+                               self.mesh.activeUVLayer = "FLTNorm2"
+                               for i, face in enumerate(self.mesh.faces):
+                                       facenorm = facenorms[i]
+                                       for j, uv in enumerate(face.uv):
+                                               facenorm[j][2] = uv[0]
+                               self.mesh.removeUVLayer("FLTNorm1")
+                               self.mesh.removeUVLayer("FLTNorm2")
+
+                               #find hard edges
+                               #store edge data for lookup by faces
+                               #edgeHash = dict()
+                               #for edge in self.mesh.edges:
+                               #       edgeHash[edge.key] = edge.index
+
+                               edgeNormHash = dict()
+                               #make sure to align the edgenormals to key value!
+                               for i, face in enumerate(self.mesh.faces):
+                                       
+                                       facenorm = facenorms[i]
+                                       faceEdges = []
+                                       faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0]))
+                                       faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1]))
+                                       if len(face.v) == 3:
+                                               faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2]))
+                                       elif len(face.v) == 4:
+                                               faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2]))
+                                               faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3]))
+                                       
+                                       #check to see if edgeNormal has been placed in the edgeNormHash yet
+                                       #this is a redundant test, and should be optimized to not be called as often as it is.
+                                       for j, faceEdge in enumerate(faceEdges):
+                                               #the value we are looking for is (faceEdge[2],faceEdge[3])
+                                               hashvalue = (faceEdge[2],faceEdge[3])
+                                               if (faceEdge[0],faceEdge[1]) != faceEdge[4]:
+                                                       hashvalue = (hashvalue[1],hashvalue[0])
+                                                       assert (faceEdge[1],faceEdge[0]) == faceEdge[4]
+                                               if edgeNormHash.has_key(faceEdge[4]):
+                                                       #compare value in the hash, if different, mark as sharp
+                                                       edgeNorm = edgeNormHash[faceEdge[4]]
+                                                       if\
+                                                       abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\
+                                                       abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\
+                                                       abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\
+                                                       abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\
+                                                       abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\
+                                                       abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE:
+                                                               edge = self.mesh.edges[edgeHash[faceEdge[4]]]
+                                                               edge.flag |= Blender.Mesh.EdgeFlags.SHARP
+                                                               
+                                               else:
+                                                       edgeNormHash[faceEdge[4]] = hashvalue
+                               
+                               #add in edgesplit modifier
+                               mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
+                               mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True
+                               mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False
+
+                       if(actuvlayer):
+                               self.mesh.activeUVLayer = actuvlayer
+               
        def blender_import(self):
-#        name = self.props['type'] + ': ' + self.props['id']
+               if self.vis and self.parent:
+                       self.vis = self.parent.vis
                name = self.props['id']
-               if self.isMesh:
-                       self.object = Blender.Object.New('Mesh', name)
-                       #self.mesh = self.object.getData()
+               
+               if self.hasMesh:
                        self.mesh = Blender.Mesh.New()
-                       self.mesh.verts.extend( Vector() ) # DUMMYVERT
-                       self.object.link(self.mesh)
+                       self.mesh.name = 'FLT_FaceList'
+                       self.mesh.fakeUser = True
+                       self.mesh.verts.extend( Vector()) #DUMMYVERT
+                       self.object = self.header.scene.objects.new(self.mesh)
                else:
-                       self.object = Blender.Object.New('Empty', name)
+                       self.object = self.header.scene.objects.new('Empty')
 
-               if self.parent:
-                       self.parent.object.makeParent([self.object])
+               self.object.name = name
+               self.header.group.objects.link(self.object)
 
-               scene.link(self.object)
-               self.object.Layer = current_layer
-               self.object.sel = 1
+               #id props import
+               self.object.properties['FLT'] = dict()
+               for key in self.props:
+                       try:
+                               self.object.properties['FLT'][key] = self.props[key]
+                       except: #horrible...
+                               pass
                
+               if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
+                               self.parent.object.makeParent([self.object])
+
+               if self.vis == False:
+                       self.object.restrictDisplay = True
+                       self.object.restrictRender = True
+               
+               else: #check for LOD children and set the proper flags
+                       lodlist = list()
+                       for child in self.children:
+                               if child.props.has_key('type') and child.props['type'] == 73:
+                                       lodlist.append(child)
+               
+                       def LODmin(a,b):
+                               if a.props['5d!switch in'] < b.props['5d!switch in']:
+                                       return a 
+                               return b
+               
+                       min= None
+                       if len(lodlist) > 1:
+                               for lod in lodlist:
+                                       lod.vis = False
+                               min = lodlist[0]
+                               for i in xrange(len(lodlist)):
+                                       min= LODmin(min,lodlist[i])
+                               min.vis = True
+                               
+               if self.matrix:
+                       self.object.setMatrix(self.matrix)
+                       
                Node.blender_import(self) # Attach faces to self.faceLs
                
-               if self.isMesh:
+               if self.hasMesh:
                        # Add all my faces into the mesh at once
                        self.blender_import_my_faces()
-               
-               if self.matrix:
-                       self.object.setMatrix(self.matrix)
-               
-               # Attach properties
-               #for name, value in self.props.items():
-               #    self.object.addProperty(name, value)
-               
+                       
        def parse_face(self):
-               child = Face(self)
+               child = Face(self, self.subfacelevel)
                child.parse()
                return True
 
@@ -838,6 +1020,11 @@ class InterNode(Node):
                child.parse()
                return True
 
+       def parse_dof(self):
+               child = DOF(self)
+               child.parse()
+               return True
+
        def parse_indexed_light_point(self):
                child = IndexedLightPoint(self)
                child.parse()
@@ -857,32 +1044,42 @@ class InterNode(Node):
                                m[i].append(f)
                self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
                
-EDGE_FGON= Blender.Mesh.EdgeFlags['FGON']
-FACE_TEX= Blender.Mesh.FaceModes['TEX']
+       def parse_subpush(self):
+               self.parse_push()
+               self.subfacelevel+= 1
+               return True
+       def  parse_subpop(self):
+               self.parse_pop()
+               self.subfacelevel -= 1
+               return True
 
+               
+               
 class Face(Node):
-       def __init__(self, parent):
+       def __init__(self, parent,subfacelevel):
                Node.__init__(self, parent, parent.header)
                self.root_handler.set_handler({31: self.parse_comment,
-                                                                          10: self.parse_push})
+                                                                          10: self.parse_push,
+                                                                          52: self.parse_multitex})
                self.root_handler.set_throw_back_lst(throw_back_opcodes)
                
                self.child_handler.set_handler({72: self.parse_vertex_list,
                                                                                10: self.parse_push,
-                                                                               11: self.parse_pop})
+                                                                               11: self.parse_pop,
+                                                                               53: self.parse_uvlist})
                
                if parent:
-                       parent.isMesh = True
+                       parent.hasMesh = True
 
-               self.indices =  list() # face verts here
+               self.subfacelevel = subfacelevel
+               self.indices =  list()  # face verts here
+               self.uvlayers = dict()  # MultiTexture layers keyed to layer bitmask.
+               self.uverts = list()    # Vertex aligned list of dictionaries keyed to layer bitmask.
+               self.uvmask = 0                 # Bitfield read from MTex record
                
                self.comment = ''
-               self.props = dict.fromkeys(['ir color', 'priority', 
-                                                                       'draw type', 'texture white', 'template billboard',
-                                                                       'smc', 'fid', 'ir material', 'lod generation control',
-                                                                       'flags', 'light mode'])
-               
-               self.header.fw.read_ahead(8) # face id
+               self.props = dict()             
+               self.props['id'] = self.header.fw.read_string(8)
                # Load face.
                self.props['ir color'] = self.header.fw.read_int()
                self.props['priority'] = self.header.fw.read_short()
@@ -919,186 +1116,14 @@ class Face(Node):
                self.alt_color_index = self.header.fw.read_uint()
                #self.header.fw.read_ahead(2)
                #self.shader_index = self.header.fw.read_short()
-       
-       
-       """
-       def blender_import_face(self, material_index, image):
-               
-               
-               mesh = self.parent.mesh
-               face_len= len(self.indices)
-               
-               mesh_vert_len_orig= len(mesh.verts)
-               mesh.verts.extend([ self.header.vert_pal.blender_verts[i] for i in self.indices])
-               
-               # Exception for an edge
-               if face_len==2:
-                       mesh.edges.extend((mesh.verts[-1], mesh.verts[-2]))
-                       return
-               
-               
-               mesh_face_indicies = range(mesh_vert_len_orig, mesh_vert_len_orig+face_len)
-               
-               #print mesh_face_indicies , 'mesh_face_indicies '
-               
-               # First we need to triangulate NGONS
-               if face_len>4:
-                       tri_indicies = [[i+mesh_vert_len_orig for i in t] for t in BPyMesh.ngon(mesh, mesh_face_indicies) ]   # use range because the verts are in order.
-               else:
-                       tri_indicies= [mesh_face_indicies] # can be a quad but thats ok
-               
-               # Extend face or ngon
-               
-               mesh.faces.extend(tri_indicies)
-               #print mesh.faces, 'mesh.faces'
-               mesh.faceUV= True
-               
-               # Now set UVs
-               for i in xrange(len(mesh.faces)-len(tri_indicies), len(mesh.faces)):
-                       f= mesh.faces[i]
-                       f_v= f.v
-                       for j, uv in enumerate(f.uv):
-                               vertex_index_flt= self.indices[f_v[j].index - mesh_vert_len_orig]
-                               
-                               vert_desc = self.header.vert_pal.vert_desc_lst[vertex_index_flt]
-                               uv.x, uv.y= vert_desc.u, vert_desc.v
-                       
-                       # Only a bug in 2.42, fixed in cvs
-                       for c in f.col:
-                               c.r=c.g=c.b= 255
-                       
-                       f.mat = material_index
-                       if image:
-                               f.image = image
-                       else:
-                               f.mode &= ~FACE_TEX
-               
-               # FGon
-               
-               if face_len>4:
-                       # Add edges we know are not fgon
-                       end_index= len(mesh.verts)
-                       start_index= end_index - len(self.indices)
-                       edge_dict= dict([ ((i, i+1), None) for i in xrange(start_index, end_index-1)])
-                       edge_dict[(start_index, end_index)]= None # wish this was a set
-                       
-                       fgon_edges= {}
-                       for tri in tri_indicies:
-                               for i in (0,1,2):
-                                       i1= tri[i]
-                                       i2= tri[i-1]
-                                       
-                                       # Sort
-                                       if i1>i2:
-                                               i1,i2= i2,i1
-                                       
-                                       if not edge_dict.has_key( (i1,i2) ): # if this works its an edge vert
-                                               fgon_edges[i1,i2]= None
-                       
-                       
-                       # Now set fgon flags
-                       for ed in mesh.edges:
-                               i1= ed.v1.index
-                               i2= ed.v2.index
-                               if i1>i2:
-                                       i1,i2= i2,i1
-                               
-                               if fgon_edges.has_key( (i1,i2) ):
-                                       # This is an edge tagged for fgonning?
-                                       fgon_edges[i1, i2]
-                                       ed.flag |= EDGE_FGON
-                                       del fgon_edges[i1, i2] # make later searches faster?
-                               
-                               if not fgon_edges:
-                                       break
-       """
-       
+
        def parse_comment(self):
                self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
                return True
                
-       # returns a tuple (material, image) where material is the blender material and
-       # image is the blender image or None.
-       def create_blender_material(self):
-                # Create face material.
-               mat_desc = MaterialDesc()
-               
-               if self.mat_index != -1:
-                       if not self.mat_index in self.header.mat_desc_pal:
-                               if global_prefs['verbose'] >= 1:
-                                       #print 'Warning: Material index', self.mat_index, 'not in material palette.'
-                                       pass
-                       else:
-                               mat_pal_desc = self.header.mat_desc_pal[self.mat_index]
-                               mat_desc.alpha = mat_pal_desc.alpha * self.alpha # combine face and mat alphas
-                               mat_desc.ambient = mat_pal_desc.ambient
-                               mat_desc.diffuse = mat_pal_desc.diffuse
-                               mat_desc.specular = mat_pal_desc.specular
-                               mat_desc.emissive = mat_pal_desc.emissive
-                               mat_desc.shininess = mat_pal_desc.shininess
-               else:
-                       # if no material get alpha from just face.
-                       mat_desc.alpha = self.alpha
-
-               # Color.
-               if global_prefs['color_from_face']:
-                       color = None
-                       if not self.props['flags'] & 0x40000000:
-                               if self.props['flags'] & 0x10000000: # packed color
-                                       color = self.packed_color
-                               else:
-                                       color = self.header.get_color(self.color_index)
-
-                       if color:
-                               r = float(color[0])/255.0
-                               g = float(color[1])/255.0
-                               b = float(color[2])/255.0
-                               mat_desc.diffuse = [r, g, b]
-
-               # Texture
-               image = None
-               if self.tex_index != -1 and self.tex_index in self.header.bl_tex_pal:
-                       mat_desc.tex0 = self.header.bl_tex_pal[self.tex_index]
-                       if mat_desc.tex0:
-                               mat_desc.name = FF.strip_path(self.header.tex_pal[self.tex_index])
-                               image = mat_desc.tex0.image
-
-               # OpenFlight Face Attributes
-               mat_desc.face_props = self.props
-               
-               # Get material.
-               mat = GRR.request_mat(mat_desc)
-               
-               # Add material to mesh.
-               mesh = self.parent.mesh
-               
-               # Return where it is in the mesh for faces.
-               mesh_materials= mesh.materials
-               
-               material_index= -1
-               for i,m in enumerate(mesh_materials):
-                       if m.name==mat.name:
-                               material_index= i
-                               break
-               
-               if material_index==-1:
-                       material_index= len(mesh_materials)
-                       if material_index==16:
-                               material_index= 15
-                               if global_prefs['verbose'] >= 1:
-                                       print 'Warning: Too many materials per mesh object. Only a maximum of 16 ' + \
-                                                 'allowed. Using 16th material instead.'
-                       
-                       else:
-                               mesh_materials.append(mat)
-                               mesh.materials= mesh_materials
-               
-               return (material_index, image)
-       
-       
        def blender_import(self):
                vert_count = len(self.indices)
-               if vert_count < 3:
+               if vert_count < 1:
                        if global_prefs['verbose'] >= 2:
                                print 'Warning: Ignoring face with no vertices.'
                        return
@@ -1106,18 +1131,21 @@ class Face(Node):
                # Assign material and image
                
                self.parent.faceLs.append(self)
-               self.blen_mat_idx, self.blen_image= self.create_blender_material()
-               
-               
-               
+               #need to store comment in mesh prop layer!
                
                # Store comment info in parent.
-               if self.comment != '':
-                       if self.parent.props['comment'] != '':
-                               self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment
-                       else:
-                               self.parent.props['comment'] = self.comment
-               
+               #if self.comment != '':
+               #       if self.parent.props['comment'] != '':
+               #               self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment
+               #       else:
+               #               self.parent.props['comment'] = self.comment
+               
+               if self.uvlayers:
+                       #Make sure that the mesh knows about the layers that this face uses
+                       self.parent.hasmtex = True
+                       for mask in self.uvlayers.keys():
+                               self.parent.uvlayers[mask] = True
+                       
        def parse_vertex_list(self):
                length = self.header.fw.get_length()
                fw = self.header.fw
@@ -1138,8 +1166,49 @@ class Face(Node):
                                          ' to vertex index.' % byte_offset
                '''
                return True
-
-
+       
+       def parse_multitex(self):
+               #Parse  MultiTex Record.
+               length = self.header.fw.get_length()
+               fw = self.header.fw
+               #num layers == (length - 8) / 4
+               uvmask = fw.read_uint()
+               mask = 2147483648
+               for i in xrange(7):
+                       if mask & uvmask:
+                               uvlayer = dict()
+                               self.uvlayers[mask] = uvlayer
+                       mask = mask / 2
+               
+               #read in record for each individual layer.
+               for key in reversed(sorted(self.uvlayers)):
+                       uvlayer = self.uvlayers[key]
+                       uvlayer['texture index'] = fw.read_ushort()
+                       uvlayer['texture enviorment'] = fw.read_ushort()
+                       uvlayer['texture mapping'] = fw.read_ushort()
+                       uvlayer['texture data'] = fw.read_ushort()
+               
+                       self.uvmask = uvmask
+               
+       def parse_uvlist(self):
+               #for each uvlayer, add uv vertices
+               length = self.header.fw.get_length()
+               fw = self.header.fw
+               uvmask = fw.read_uint()
+               if uvmask != self.uvmask: #This should never happen!
+                       fw.read_ahead(self.length -  4) #potentially unnessecary?
+               else:   
+                       #need to store in uvverts dictionary for each vertex.
+                       totverts = len(self.indices)
+                       for i in xrange(totverts):
+                               uvert = dict()
+                               for key in reversed(sorted(self.uvlayers)):
+                                       uv = Vector(0.0,0.0)
+                                       uv[0] = fw.read_float()
+                                       uv[1] = fw.read_float()
+                                       uvert[key] = uv
+                               self.uverts.append(uvert)
+                               
 class Object(InterNode):
        def __init__(self, parent):
                Node.__init__(self, parent, parent.header)
@@ -1152,15 +1221,15 @@ class Object(InterNode):
                self.root_handler.set_throw_back_lst(throw_back_opcodes)
                
                self.child_handler.set_handler({5: self.parse_face,
-                                                                               #130: self.parse_indexed_light_point,
-                                                                               #111: self.parse_inline_light_point,
+                                                                               19: self.parse_subpush,
+                                                                               20: self.parse_subpop,
+                                                                               111: self.parse_inline_light_point,
                                                                                10: self.parse_push,
                                                                                11: self.parse_pop})
 
-               self.props['type'] = 'Object'
-               self.props['id'] = self.header.fw.read_string(8)
-
-
+               self.props = dict()             
+               self.props['comment'] = ''
+               self.parse_record()
 
 class Group(InterNode):
        def __init__(self, parent):
@@ -1174,15 +1243,16 @@ class Group(InterNode):
                self.root_handler.set_throw_back_lst(throw_back_opcodes)
                
                self.child_handler.set_handler({5: self.parse_face,
-                                                                               #130: self.parse_indexed_light_point,
-                                                                               #111: self.parse_inline_light_point,
+                                                                               19: self.parse_subpush,
+                                                                               20: self.parse_subpop,
+                                                                               111: self.parse_inline_light_point,
                                                                                2: self.parse_group,
                                                                                73: self.parse_lod,
                                                                                4: self.parse_object,
                                                                                10: self.parse_push,
                                                                                11: self.parse_pop,
                                                                                96: self.parse_unhandled,
-                                                                               14: self.parse_unhandled,
+                                                                               14: self.parse_dof,
                                                                                91: self.parse_unhandled,
                                                                                98: self.parse_unhandled,
                                                                                63: self.parse_xref})
@@ -1190,20 +1260,48 @@ class Group(InterNode):
                                                                        'special2', 'significance', 'layer code', 'loop count',
                                                                        'loop duration', 'last frame duration'])
                
-               self.props['type'] = 'Group'
                self.props['comment'] = ''
-               self.props['id'] = self.header.fw.read_string(8)
-               self.props['priority'] = self.header.fw.read_short()
-               self.header.fw.read_ahead(2)
-               self.props['flags'] = self.header.fw.read_int()
-               self.props['special1'] = self.header.fw.read_short()
-               self.props['special2'] = self.header.fw.read_short()
-               self.props['significance'] = self.header.fw.read_short()
-               self.props['layer code'] = self.header.fw.read_char()
-               self.header.fw.read_ahead(5)
-               self.props['loop count'] = self.header.fw.read_int()
-               self.props['loop duration'] = self.header.fw.read_float()
-               self.props['last frame duration'] = self.header.fw.read_float()               
+               self.parse_record()
+               
+               #self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode]
+               #props = records[self.opcode]
+               #propkeys = props.keys()
+               #propkeys.sort()
+               #for position in propkeys:
+               #       (type,length,name) = props[position]
+               #       self.props[name] = read_prop(self.header.fw,type,length)
+               #self.props['id'] = self.props['3t8!id']
+
+class DOF(InterNode):
+       def blender_import(self):
+               InterNode.blender_import(self)
+
+       def __init__(self, parent):
+               Node.__init__(self, parent, parent.header)
+               InterNode.__init__(self)
+               
+               self.root_handler.set_handler({33: self.parse_long_id,
+                                                                          31: self.parse_comment,
+                                                                          10: self.parse_push,
+                                                                          49: self.parse_matrix})
+               self.root_handler.set_throw_back_lst(throw_back_opcodes)
+               
+               self.child_handler.set_handler({#130: self.parse_indexed_light_point,
+                                                                               111: self.parse_inline_light_point,
+                                                                               2: self.parse_group,
+                                                                               73: self.parse_lod,
+                                                                               4: self.parse_object,
+                                                                               10: self.parse_push,
+                                                                               11: self.parse_pop,
+                                                                               96: self.parse_unhandled,
+                                                                               14: self.parse_dof,
+                                                                               91: self.parse_unhandled,
+                                                                               98: self.parse_unhandled,
+                                                                               63: self.parse_xref})
+               self.props = dict()             
+               self.props['comment'] = ''
+               self.parse_record()
+
 
 class XRef(InterNode):
        def parse(self):
@@ -1214,31 +1312,66 @@ class XRef(InterNode):
        def __init__(self, parent):
                Node.__init__(self, parent, parent.header)
                InterNode.__init__(self)
-
+               
                self.root_handler.set_handler({49: self.parse_matrix})
                self.root_handler.set_throw_back_lst(throw_back_opcodes)
                
-               xref_filename = self.header.fw.read_string(200)
-               filename = FF.find(xref_filename)
+               self.props = dict()             
+               self.props['comment'] = ''
+               self.parse_record()
 
-               self.props['type'] = 'XRef'
+               xref_filename = self.props['3t200!filename']
+               self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
                
-               if filename != None:
-                       self.xref = Database(filename, self)
-                       self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(filename))[0]
+               if global_prefs['doxrefs'] and os.path.exists(xref_filename) and not self.header.grr.xrefs.has_key(xref_filename):
+                       self.xref = Database(xref_filename, self.header.grr, self)
+                       self.header.grr.xrefs[xref_filename] = self.xref
                else:
                        self.xref = None
-                       self.props['id'] = 'X: broken'
+               
+
+       def blender_import(self):
+               #name = self.props['type'] + ': ' + self.props['id']
+               name = self.props['id']
+               self.object = self.header.scene.objects.new('Empty')
+               self.object.name = name
+               self.object.enableDupGroup = True
+               self.header.group.objects.link(self.object)
+               
+               #for broken links its ok to leave this empty! they purely for visual purposes anyway.....
+               try:
+                       self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group
+               except:
+                       pass
+                       
+               if self.parent and self.parent.object:
+                       self.parent.object.makeParent([self.object])
 
+               #id props import
+               self.object.properties['FLT'] = dict()
+               for key in self.props:
+                       try:
+                               self.object.properties['FLT'][key] = self.props[key]
+                       except: #horrible...
+                               pass
+
+               self.object.Layer = current_layer
+               self.object.sel = 1
+               if self.matrix:
+                       self.object.setMatrix(self.matrix)
+               Node.blender_import(self)
+               
+               
 class LOD(InterNode):
        def blender_import(self):
-               self.move_to_next_layer()
+               #self.move_to_next_layer()
                InterNode.blender_import(self)
-
+               #self.object.properties['FLT'] = self.props.copy()
+               
        def __init__(self, parent):
                Node.__init__(self, parent, parent.header)
                InterNode.__init__(self)
-               
+
                self.root_handler.set_handler({33: self.parse_long_id,
                                                                           31: self.parse_comment,
                                                                           10: self.parse_push,