svn merge -r41779:41847 ^/trunk/blender
authorCampbell Barton <ideasman42@gmail.com>
Tue, 15 Nov 2011 02:58:06 +0000 (02:58 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 15 Nov 2011 02:58:06 +0000 (02:58 +0000)
40 files changed:
1  2 
CMakeLists.txt
release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/mesh_validate.c
source/blender/blenkernel/intern/object.c
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/intern/math_geom.c
source/blender/blenlib/intern/math_vector_inline.c
source/blender/blenlib/intern/path_util.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_object_api.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/MOD_modifiertypes.h
source/blender/modifiers/SConscript
source/blender/modifiers/intern/MOD_ocean.c
source/blender/modifiers/intern/MOD_util.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/render_texture.c
source/blenderplayer/bad_level_call_stubs/stubs.c

diff --cc CMakeLists.txt
Simple merge
Simple merge
@@@ -159,7 -159,7 +159,8 @@@ void OBJECT_OT_multires_external_save(s
  void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
  void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
  void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
+ void OBJECT_OT_ocean_bake(struct wmOperatorType *ot);
 +void OBJECT_OT_test_multires(struct wmOperatorType *ot);
  
  /* object_constraint.c */
  void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
  #include "BKE_multires.h"
  #include "BKE_report.h"
  #include "BKE_object.h"
+ #include "BKE_ocean.h"
  #include "BKE_particle.h"
  #include "BKE_softbody.h"
 +#include "BKE_tessmesh.h"
  
  #include "RNA_access.h"
  #include "RNA_define.h"
@@@ -2819,28 -2735,35 +2819,34 @@@ static void draw_em_fancy(Scene *scene
        if(dt>OB_WIRE) {
                if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
                        if(draw_glsl_material(scene, ob, v3d, dt)) {
-                               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+                               /* if em has no faces the drawMappedFaces callback will fail */
 -                              if(em->faces.first) {
++                              if(em->bm->totface) {
+                                       glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
  
-                               finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
-                                       draw_em_fancy__setGLSLFaceOpts, em);
-                               GPU_disable_material();
+                                       finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
 -                                                                                               draw_em_fancy__setGLSLFaceOpts, NULL);
++                                                                   draw_em_fancy__setGLSLFaceOpts, em);
+                                       GPU_disable_material();
  
-                               glFrontFace(GL_CCW);
+                                       glFrontFace(GL_CCW);
+                               }
                        }
                        else {
                                draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
                        }
                }
                else {
-                       /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
-                       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
+                       /* if em has no faces the drawMappedFaces callback will fail */
 -                      if(em->faces.first) {
++                      if(em->bm->totface) {
+                               /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
+                               glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
  
-                       glEnable(GL_LIGHTING);
-                       glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
-                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
+                               glEnable(GL_LIGHTING);
+                               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 -
 -                              finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
++                              finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
  
-                       glFrontFace(GL_CCW);
-                       glDisable(GL_LIGHTING);
+                               glFrontFace(GL_CCW);
+                               glDisable(GL_LIGHTING);
+                       }
                }
                        
                // Setup for drawing wire over, disable zbuffer
@@@ -73,11 -73,8 +73,11 @@@ typedef enum ModifierType 
        eModifierType_WeightVGEdit,
        eModifierType_WeightVGMix,
        eModifierType_WeightVGProximity,
-       eModifierType_EmptySlot,    /* keep so DynamicPaint keep loading, can re-use later */
-       eModifierType_DynamicPaint, /* reserve slot */
+       eModifierType_Ocean,
+       eModifierType_DynamicPaint,
 +
 +      /* BMESH ONLY - keeps getting bumped by new modifiers in trunk */
 +      eModifierType_NgonInterp,
        NUM_MODIFIER_TYPES
  } ModifierType;
  
@@@ -754,13 -750,67 +754,72 @@@ typedef struct ScrewModifierData 
  #define MOD_SCREW_OBJECT_OFFSET       (1<<2)
  // #define MOD_SCREW_OBJECT_ANGLE     (1<<4)
  
 -typedef struct WarpModifierData {
+ typedef struct OceanModifierData {
+       ModifierData modifier;          
+       
+       struct Ocean *ocean;
+       struct OceanCache *oceancache;
+       
+       int             resolution;
+       int             spatial_size;
+       
+       float   wind_velocity;
+       
+       float   damp;
+       float   smallest_wave;
+       float   depth;
+       
+       float   wave_alignment;
+       float   wave_direction;
+       float   wave_scale;
+       
+       float   chop_amount;
+       float   foam_coverage;
+       float   time;
+       
+       int             seed;
+       int             flag;
+       int             output;
+       
+       int             refresh;
+       
+       int             bakestart;
+       int             bakeend;
+       
+       char    cachepath[240]; // FILE_MAX
+       int             cached;
+       
+       int             geometry_mode;
+       float   size;
+       int             repeat_x;
+       int             repeat_y;
+       
+       float   foam_fade;
+       
+ } OceanModifierData;
+ #define MOD_OCEAN_GEOM_GENERATE       0
+ #define MOD_OCEAN_GEOM_DISPLACE       1
+ #define MOD_OCEAN_GEOM_SIM_ONLY       2
+ #define MOD_OCEAN_REFRESH_RESET                       1
+ #define MOD_OCEAN_REFRESH_SIM                 2
+ #define MOD_OCEAN_REFRESH_ADD                 4
+ #define MOD_OCEAN_REFRESH_CLEAR_CACHE 8
+ #define MOD_OCEAN_REFRESH_TOPOLOGY            16
+ #define MOD_OCEAN_GENERATE_FOAM       1
+ #define MOD_OCEAN_GENERATE_NORMALS    2
++/* BMESH_ONLY */
 +typedef struct NgonInterpModifierData {
        ModifierData modifier;
 +      int             resolution, pad0;
 +} NgonInterpModifierData;
  
 +typedef struct WarpModifierData {
 +      ModifierData modifier;
        /* keep in sync with MappingInfoModifierData */
        struct Tex *texture;
        struct Object *map_object;
Simple merge
Simple merge
@@@ -95,8 -97,6 +97,7 @@@ EnumPropertyItem modifier_type_items[] 
        {eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
        {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
        {eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
-       {eModifierType_DynamicPaint, "DYNAMIC_PAINT", ICON_MOD_DYNAMICPAINT, "Dynamic Paint", ""},
 +      {eModifierType_NgonInterp, "NGONINTERP", ICON_MOD_LATTICE, "Precision UV Interpolation", ""},
        {0, NULL, 0, NULL, NULL}};
  
  #ifdef RNA_RUNTIME
@@@ -2812,25 -2863,180 +2866,202 @@@ static void rna_def_modifier_weightvgpr
        rna_def_modifier_weightvg_mask(brna, srna);
  }
  
 +
+ static void rna_def_modifier_ocean(BlenderRNA *brna)
+ {
+       StructRNA *srna;
+       PropertyRNA *prop;
+       
+       static EnumPropertyItem geometry_items[]= {
+               {MOD_OCEAN_GEOM_GENERATE, "GENERATE", 0, "Generate", "Generates ocean surface geometry at the specified resolution"},
+               {MOD_OCEAN_GEOM_DISPLACE, "DISPLACE", 0, "Displace", "Displaces existing geometry according to simulation"},
+               //{MOD_OCEAN_GEOM_SIM_ONLY, "SIM_ONLY", 0, "Sim Only", "Leaves geometry unchanged, but still runs simulation (to be used from texture)"},
+               {0, NULL, 0, NULL, NULL}};
+       
+       srna= RNA_def_struct(brna, "OceanModifier", "Modifier");
+       RNA_def_struct_ui_text(srna, "Ocean Modifier", "Simulate an ocean surface");
+       RNA_def_struct_sdna(srna, "OceanModifierData");
+       RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM);
+       
+       /* General check if blender was built with OceanSim modifier support */
+       prop= RNA_def_property(srna, "is_build_enabled", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_OceanModifier_is_build_enabled_get", NULL);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Build Enabled", "True if the OceanSim modifier is enabled in this build");
+       
+       prop= RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "geometry_mode");
+       RNA_def_property_enum_items(prop, geometry_items);
+       RNA_def_property_ui_text(prop, "Geometry", "Method of modifying geometry");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+       
+       prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "size");
+       RNA_def_property_ui_text(prop, "Size", "");
+       RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update");
+       
+       prop= RNA_def_property(srna, "repeat_x", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "repeat_x");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_range(prop, 1, 1024);
+       RNA_def_property_ui_range(prop, 1, 100, 1, 0);
+       RNA_def_property_ui_text(prop, "Repeat X", "Repetitions of the generated surface in X");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update");
+       
+       prop= RNA_def_property(srna, "repeat_y", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "repeat_y");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_range(prop, 1, 1024);
+       RNA_def_property_ui_range(prop, 1, 100, 1, 0);
+       RNA_def_property_ui_text(prop, "Repeat Y", "Repetitions of the generated surface in Y");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update");
+       prop= RNA_def_property(srna, "use_normals", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_GENERATE_NORMALS);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Generate Normals", "Outputs normals for bump mapping - disabling can speed up performance if its not needed");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "use_foam", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_GENERATE_FOAM);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Generate Foam", "Generates foam mask as a vertex color channel");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "resolution");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_range(prop, 1, 1024);
+       RNA_def_property_ui_range(prop, 1, 32, 1, 0);
+       RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "spatial_size", PROP_INT, PROP_DISTANCE);
+       RNA_def_property_int_sdna(prop, NULL, "spatial_size");
+       RNA_def_property_ui_range(prop, 1, 512, 2, 0);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Spatial Size", "Physical size of the simulation domain (m)");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "wind_velocity", PROP_FLOAT, PROP_VELOCITY);
+       RNA_def_property_float_sdna(prop, NULL, "wind_velocity");
+       RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed (m/s)");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "damping", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "damp");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Damping", "Damp reflected waves going in opposite direction to the wind");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "wave_scale_min", PROP_FLOAT, PROP_DISTANCE);
+       RNA_def_property_float_sdna(prop, NULL, "smallest_wave");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_range(prop, 0.0, FLT_MAX);
+       RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength (m)");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "wave_alignment", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "wave_alignment");
+       RNA_def_property_range(prop, 0.0, 10.0);
+       RNA_def_property_ui_text(prop, "Wave Alignment", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "wave_direction", PROP_FLOAT, PROP_ANGLE);
+       RNA_def_property_float_sdna(prop, NULL, "wave_direction");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Wave Direction", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "wave_scale", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "wave_scale");
+       RNA_def_property_ui_text(prop, "Wave Scale", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
+       
+       prop= RNA_def_property(srna, "depth", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "depth");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Depth", "");
+       RNA_def_property_ui_range(prop, 0, 250, 1, 0);
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "foam_coverage", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "foam_coverage");
+       RNA_def_property_ui_text(prop, "Foam Coverage", "");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+       
+       prop= RNA_def_property(srna, "bake_foam_fade", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "foam_fade");
+       RNA_def_property_ui_text(prop, "Foam Fade", "");
+       RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
+       RNA_def_property_update(prop, 0, NULL);
+       
+       prop= RNA_def_property(srna, "choppiness", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "chop_amount");
+       RNA_def_property_ui_text(prop, "Choppiness", "");
+       RNA_def_property_ui_range(prop, 0.0, 4.0, 3, 0);
+       RNA_def_property_float_funcs(prop, NULL, "rna_OceanModifier_ocean_chop_set", NULL);
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
+       
+       prop= RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_sdna(prop, NULL, "time");
+       RNA_def_property_ui_text(prop, "Time", "");
+       RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
+       
+       prop= RNA_def_property(srna, "random_seed", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "seed");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Random Seed", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "frame_start", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "bakestart");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Bake Start", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "frame_end", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "bakeend");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Bake End", "");
+       RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
+       
+       prop= RNA_def_property(srna, "is_cached", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cached", 1);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Ocean is Cached", "Whether the ocean is useing cached data or simulating");
+       prop= RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH);
+       RNA_def_property_string_sdna(prop, NULL, "cachepath");
+       RNA_def_property_ui_text(prop, "Cache Path", "Path to a folder to store external baked images");
+       //RNA_def_property_update(prop, 0, "rna_Modifier_update");
+       // XXX how to update?
+ }
 +
 +static void rna_def_modifier_ngoninterp(BlenderRNA *brna)
 +{
 +      StructRNA *srna;
 +      PropertyRNA *prop;
 +
 +      srna= RNA_def_struct(brna, "NgonInterpModifier", "Modifier");
 +      RNA_def_struct_ui_text(srna, "Precision UV Modifier", "Precision UV interpolation");
 +      RNA_def_struct_sdna(srna, "NgonInterpModifierData");
 +      RNA_def_struct_ui_icon(srna, ICON_MOD_SCREW);
 +
 +      prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_UNSIGNED);
 +      RNA_def_property_range(prop, 1, 10000);
 +      RNA_def_property_ui_range(prop, 1, 100, 1, 0);
 +      RNA_def_property_ui_text(prop, "Resolution", "Size of interpolation grids");
 +      RNA_def_property_update(prop, 0, "rna_Modifier_update");
 +
 +}
++
++
++
  void RNA_def_modifier(BlenderRNA *brna)
  {
        StructRNA *srna;
        rna_def_modifier_weightvgmix(brna);
        rna_def_modifier_weightvgproximity(brna);
        rna_def_modifier_dynamic_paint(brna);
+       rna_def_modifier_ocean(brna);
++
++
++      /* BMESH_ONLY */
 +      rna_def_modifier_ngoninterp(brna);
  }
  
  #endif
@@@ -67,8 -66,8 +67,9 @@@ set(SR
        intern/MOD_meshdeform.c
        intern/MOD_mirror.c
        intern/MOD_multires.c
 +      intern/MOD_ngoninterp.c
        intern/MOD_none.c
+       intern/MOD_ocean.c
        intern/MOD_particleinstance.c
        intern/MOD_particlesystem.c
        intern/MOD_screw.c
Simple merge
index 0000000,e0ccb1f..9cfdb70
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,560 +1,560 @@@
 -                                                                      struct EditMesh *UNUSED(editData),
+ /**
+  * ***** BEGIN GPL LICENSE BLOCK *****
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+  * of the License, or (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+  *
+  * The Original Code is Copyright (C) Blender Foundation
+  * All rights reserved.
+  *
+  * The Original Code is: all of this file.
+  *
+  * Contributor(s): Matt Ebb
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ #include "MEM_guardedalloc.h"
+ #include "DNA_customdata_types.h"
+ #include "DNA_object_types.h"
+ #include "DNA_meshdata_types.h"
+ #include "DNA_modifier_types.h"
+ #include "DNA_scene_types.h"
+ #include "BKE_cdderivedmesh.h"
+ #include "BKE_modifier.h"
+ #include "BKE_ocean.h"
+ #include "BKE_utildefines.h"
+ #include "BLI_math.h"
+ #include "BLI_math_inline.h"
+ #include "BLI_utildefines.h"
+ #include "BLI_string.h"
+ #include "MOD_util.h"
+ #ifdef WITH_OCEANSIM
+ static void init_cache_data(struct OceanModifierData *omd)
+ {
+       omd->oceancache = BKE_init_ocean_cache(omd->cachepath, omd->bakestart, omd->bakeend, omd->wave_scale,
+                                                                                  omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
+ }
+ static void clear_cache_data(struct OceanModifierData *omd)
+ {
+       BKE_free_ocean_cache(omd->oceancache);
+       omd->oceancache = NULL;
+       omd->cached = FALSE;
+ }
+ /* keep in sync with init_ocean_modifier_bake(), object_modifier.c */
+ static void init_ocean_modifier(struct OceanModifierData *omd)
+ {
+       int do_heightfield, do_chop, do_normals, do_jacobian;
+       if (!omd || !omd->ocean) return;
+       do_heightfield = TRUE;
+       do_chop = (omd->chop_amount > 0);
+       do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
+       do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
+       BKE_free_ocean_data(omd->ocean);
+       BKE_init_ocean(omd->ocean, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size,
+                                  omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
+                                  omd->depth, omd->time,
+                                  do_heightfield, do_chop, do_normals, do_jacobian,
+                                  omd->seed);
+ }
+ static void simulate_ocean_modifier(struct OceanModifierData *omd)
+ {
+       if (!omd || !omd->ocean) return;
+       BKE_simulate_ocean(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
+ }
+ #endif // WITH_OCEANSIM
+ /* Modifier Code */
+ static void initData(ModifierData *md)
+ {
+ #ifdef WITH_OCEANSIM
+       OceanModifierData *omd = (OceanModifierData*) md;
+       omd->resolution = 7;
+       omd->spatial_size = 50;
+       omd->wave_alignment = 0.0;
+       omd->wind_velocity = 30.0;
+       omd->damp = 0.5;
+       omd->smallest_wave = 0.01;
+       omd->wave_direction= 0.0;
+       omd->depth = 200.0;
+       omd->wave_scale = 1.0;
+       omd->chop_amount = 1.0;
+       omd->foam_coverage = 0.0;
+       omd->seed = 0;
+       omd->time = 1.0;
+       omd->refresh = 0;
+       omd->size = 1.0;
+       omd->repeat_x = 1;
+       omd->repeat_y = 1;
+       BLI_strncpy(omd->cachepath, "//ocean_cache", sizeof(omd->cachepath));
+       omd->cached = 0;
+       omd->bakestart = 1;
+       omd->bakeend = 250;
+       omd->oceancache = NULL;
+       omd->foam_fade = 0.98;
+       omd->ocean = BKE_add_ocean();
+       init_ocean_modifier(omd);
+       simulate_ocean_modifier(omd);
+ #else  // WITH_OCEANSIM
+       /* unused */
+       (void)md;
+ #endif // WITH_OCEANSIM
+ }
+ static void freeData(ModifierData *md)
+ {
+ #ifdef WITH_OCEANSIM
+       OceanModifierData *omd = (OceanModifierData*) md;
+       BKE_free_ocean(omd->ocean);
+       if (omd->oceancache)
+               BKE_free_ocean_cache(omd->oceancache);
+ #else // WITH_OCEANSIM
+       /* unused */
+       (void)md;
+ #endif // WITH_OCEANSIM
+ }
+ static void copyData(ModifierData *md, ModifierData *target)
+ {
+ #ifdef WITH_OCEANSIM
+       OceanModifierData *omd = (OceanModifierData*) md;
+       OceanModifierData *tomd = (OceanModifierData*) target;
+       tomd->resolution = omd->resolution;
+       tomd->spatial_size = omd->spatial_size;
+       tomd->wind_velocity = omd->wind_velocity;
+       tomd->damp = omd->damp;
+       tomd->smallest_wave = omd->smallest_wave;
+       tomd->depth = omd->depth;
+       tomd->wave_alignment = omd->wave_alignment;
+       tomd->wave_direction = omd->wave_direction;
+       tomd->wave_scale = omd->wave_scale;
+       tomd->chop_amount = omd->chop_amount;
+       tomd->foam_coverage = omd->foam_coverage;
+       tomd->time = omd->time;
+       tomd->seed = omd->seed;
+       tomd->flag = omd->flag;
+       tomd->output = omd->output;
+       tomd->refresh = 0;
+       tomd->size = omd->size;
+       tomd->repeat_x = omd->repeat_x;
+       tomd->repeat_y = omd->repeat_y;
+       /* XXX todo: copy cache runtime too */
+       tomd->cached = 0;
+       tomd->bakestart = omd->bakestart;
+       tomd->bakeend = omd->bakeend;
+       tomd->oceancache = NULL;
+       tomd->ocean = BKE_add_ocean();
+       init_ocean_modifier(tomd);
+       simulate_ocean_modifier(tomd);
+ #else // WITH_OCEANSIM
+       /* unused */
+       (void)md;
+       (void)target;
+ #endif // WITH_OCEANSIM
+ }
+ #ifdef WITH_OCEANSIM
+ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+ {
+       OceanModifierData *omd = (OceanModifierData *)md;
+       CustomDataMask dataMask = 0;
+       if (omd->flag & MOD_OCEAN_GENERATE_FOAM)
+               dataMask |= CD_MASK_MCOL;
+       return dataMask;
+ }
+ #else // WITH_OCEANSIM
+ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+ {
+       /* unused */
+       (void)md;
+       return 0;
+ }
+ #endif // WITH_OCEANSIM
+ #if 0
+ static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
+ {
+       /* get bounding box of underlying dm */
+       int v, totvert=dm->getNumVerts(dm);
+       float min[3], max[3], delta[3];
+       MVert *mvert = dm->getVertDataArray(dm,0);
+       copy_v3_v3(min, mvert->co);
+       copy_v3_v3(max, mvert->co);
+       for(v=1; v<totvert; v++, mvert++) {
+               min[0]=MIN2(min[0],mvert->co[0]);
+               min[1]=MIN2(min[1],mvert->co[1]);
+               min[2]=MIN2(min[2],mvert->co[2]);
+               max[0]=MAX2(max[0],mvert->co[0]);
+               max[1]=MAX2(max[1],mvert->co[1]);
+               max[2]=MAX2(max[2],mvert->co[2]);
+       }
+       sub_v3_v3v3(delta, max, min);
+       *sx = delta[0];
+       *sy = delta[1];
+       *ox = min[0];
+       *oy = min[1];
+ }
+ #endif
+ #ifdef WITH_OCEANSIM
+ MINLINE float ocean_co(OceanModifierData *omd, float v)
+ {
+       //float scale = 1.0 / (omd->size * omd->spatial_size);
+       //*v = (*v * scale) + 0.5;
+       return (v / (omd->size * omd->spatial_size)) + 0.5f;
+ }
+ #define OMP_MIN_RES   18
+ static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
+ {
+       DerivedMesh *result;
+       MVert *mv;
+       MFace *mf;
+       MTFace *tf;
+       int cdlayer;
+       const int rx = omd->resolution*omd->resolution;
+       const int ry = omd->resolution*omd->resolution;
+       const int res_x = rx * omd->repeat_x;
+       const int res_y = ry * omd->repeat_y;
+       const int num_verts = (res_x + 1) * (res_y + 1);
+       const int num_edges = (res_x * res_y * 2) + res_x + res_y;
+       const int num_faces = res_x * res_y;
+       float sx = omd->size * omd->spatial_size;
+       float sy = omd->size * omd->spatial_size;
+       const float ox = -sx / 2.0f;
+       const float oy = -sy / 2.0f;
+       float ix, iy;
+       int x, y;
+       sx /= rx;
+       sy /= ry;
+       result = CDDM_new(num_verts, num_edges, num_faces);
+       mv = CDDM_get_verts(result);
+       mf = CDDM_get_faces(result);
+       /* create vertices */
+       #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
+       for (y=0; y < res_y+1; y++) {
+               for (x=0; x < res_x+1; x++) {
+                       const int i = y*(res_x+1) + x;
+                       mv[i].co[0] = ox + (x * sx);
+                       mv[i].co[1] = oy + (y * sy);
+                       mv[i].co[2] = 0;
+               }
+       }
+       /* create faces */
+       #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
+       for (y=0; y < res_y; y++) {
+               for (x=0; x < res_x; x++) {
+                       const int fi = y*res_x + x;
+                       const int vi = y*(res_x+1) + x;
+                       mf[fi].v1 = vi;
+                       mf[fi].v2 = vi + 1;
+                       mf[fi].v3 = vi + 1 + res_x+1;
+                       mf[fi].v4 = vi + res_x+1;
+                       mf[fi].flag |= ME_SMOOTH;
+               }
+       }
+       CDDM_calc_edges(result);
+       /* add uvs */
+       cdlayer= CustomData_number_of_layers(&result->faceData, CD_MTFACE);
+       if(cdlayer >= MAX_MTFACE)
+               return result;
+       CustomData_add_layer(&result->faceData, CD_MTFACE, CD_CALLOC, NULL, num_faces);
+       tf = CustomData_get_layer(&result->faceData, CD_MTFACE);
+       ix = 1.0 / rx;
+       iy = 1.0 / ry;
+       #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
+       for (y=0; y < res_y; y++) {
+               for (x=0; x < res_x; x++) {
+                       const int i = y*res_x + x;
+                       tf[i].uv[0][0] = x * ix;
+                       tf[i].uv[0][1] = y * iy;
+                       tf[i].uv[1][0] = (x+1) * ix;
+                       tf[i].uv[1][1] = y * iy;
+                       tf[i].uv[2][0] = (x+1) * ix;
+                       tf[i].uv[2][1] = (y+1) * iy;
+                       tf[i].uv[3][0] = x * ix;
+                       tf[i].uv[3][1] = (y+1) * iy;
+               }
+       }
+       return result;
+ }
+ static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
+                                                         DerivedMesh *derivedData,
+                                                         int UNUSED(useRenderParams))
+ {
+       OceanModifierData *omd = (OceanModifierData*) md;
+       DerivedMesh *dm=NULL;
+       OceanResult ocr;
+       MVert *mv;
+       MFace *mf;
+       int cdlayer;
+       int i, j;
+       int num_verts;
+       int num_faces;
+       int cfra;
+       /* update modifier */
+       if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
+               omd->ocean = BKE_add_ocean();
+       if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
+               init_ocean_modifier(omd);
+       if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
+               clear_cache_data(omd);
+       omd->refresh = 0;
+       /* do ocean simulation */
+       if (omd->cached == TRUE) {
+               if (!omd->oceancache) init_cache_data(omd);
+               BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra);
+       } else {
+               simulate_ocean_modifier(omd);
+       }
+       if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE)
+               dm = generate_ocean_geometry(omd);
+       else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
+               dm = CDDM_copy(derivedData);
+       }
+       cfra = md->scene->r.cfra;
+       CLAMP(cfra, omd->bakestart, omd->bakeend);
+       cfra -= omd->bakestart; // shift to 0 based
+       num_verts = dm->getNumVerts(dm);
+       num_faces = dm->getNumFaces(dm);
+       /* add vcols before displacement - allows lookup based on position */
+       if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
+               MCol *mc;
+               float foam;
+               char cf;
+               float u=0.0, v=0.0;
+               cdlayer= CustomData_number_of_layers(&dm->faceData, CD_MCOL);
+               if(cdlayer >= MAX_MCOL)
+                       return dm;
+               CustomData_add_layer(&dm->faceData, CD_MCOL, CD_CALLOC, NULL, num_faces);
+               mc = dm->getFaceDataArray(dm, CD_MCOL);
+               mv = dm->getVertArray(dm);
+               mf = dm->getFaceArray(dm);
+               for (i = 0; i < num_faces; i++, mf++) {
+                       for (j=0; j<4; j++) {
+                               if (j == 3 && !mf->v4) continue;
+                               switch(j) {
+                                       case 0:
+                                               u = ocean_co(omd, mv[mf->v1].co[0]);
+                                               v = ocean_co(omd, mv[mf->v1].co[1]);
+                                               break;
+                                       case 1:
+                                               u = ocean_co(omd, mv[mf->v2].co[0]);
+                                               v = ocean_co(omd, mv[mf->v2].co[1]);
+                                               break;
+                                       case 2:
+                                               u = ocean_co(omd, mv[mf->v3].co[0]);
+                                               v = ocean_co(omd, mv[mf->v3].co[1]);
+                                               break;
+                                       case 3:
+                                               u = ocean_co(omd, mv[mf->v4].co[0]);
+                                               v = ocean_co(omd, mv[mf->v4].co[1]);
+                                               break;
+                               }
+                               if (omd->oceancache && omd->cached==TRUE) {
+                                       BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
+                                       foam = ocr.foam;
+                                       CLAMP(foam, 0.0f, 1.0f);
+                               } else {
+                                       BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
+                                       foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
+                               }
+                               cf = (char)(foam*255);
+                               mc[i*4 + j].r = mc[i*4 + j].g = mc[i*4 + j].b = cf;
+                               mc[i*4 + j].a = 255;
+                       }
+               }
+       }
+       /* displace the geometry */
+       mv = dm->getVertArray(dm);
+       //#pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES)
+       for (i=0; i< num_verts; i++) {
+               const float u = ocean_co(omd, mv[i].co[0]);
+               const float v = ocean_co(omd, mv[i].co[1]);
+               if (omd->oceancache && omd->cached==TRUE)
+                       BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
+               else
+                       BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
+               mv[i].co[2] += ocr.disp[1];
+               if (omd->chop_amount > 0.0f) {
+                       mv[i].co[0] += ocr.disp[0];
+                       mv[i].co[1] += ocr.disp[2];
+               }
+       }
+       return dm;
+ }
+ #else  // WITH_OCEANSIM
+ static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
+                                                         DerivedMesh *derivedData,
+                                                         int UNUSED(useRenderParams))
+ {
+       /* unused */
+       (void)md;
+       return derivedData;
+ }
+ #endif // WITH_OCEANSIM
+ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+                                                                 DerivedMesh *derivedData,
+                                                                 int UNUSED(useRenderParams),
+                                                                 int UNUSED(isFinalCalc))
+ {
+       DerivedMesh *result;
+       result = doOcean(md, ob, derivedData, 0);
+       if(result != derivedData)
+               CDDM_calc_normals(result);
+       return result;
+ }
+ static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
++                                                                      struct BMEditMesh *UNUSED(editData),
+                                                                       DerivedMesh *derivedData)
+ {
+       return applyModifier(md, ob, derivedData, 0, 1);
+ }
+ ModifierTypeInfo modifierType_Ocean = {
+       /* name */              "Ocean",
+       /* structName */        "OceanModifierData",
+       /* structSize */        sizeof(OceanModifierData),
+       /* type */              eModifierTypeType_Constructive,
+       /* flags */             eModifierTypeFlag_AcceptsMesh
+                                                       | eModifierTypeFlag_SupportsEditmode
+                                                       | eModifierTypeFlag_EnableInEditmode,
+       /* copyData */          copyData,
+       /* deformMatrices */    NULL,
+       /* deformVerts */       NULL,
+       /* deformVertsEM */     NULL,
+       /* deformMatricesEM */  NULL,
+       /* applyModifier */     applyModifier,
+       /* applyModifierEM */   applyModifierEM,
+       /* initData */          initData,
+       /* requiredDataMask */  requiredDataMask,
+       /* freeData */          freeData,
+       /* isDisabled */        NULL,
+       /* updateDepgraph */    NULL,
+       /* dependsOnTime */     NULL,
+       /* dependsOnNormals */  NULL,
+       /* foreachObjectLink */ NULL,
+       /* foreachIDLink */     NULL,
+ };