Browse Source

SeaPatchNode initial version based on DQ Pirates SeaPatchNode

Shalin Shodhan 21 years ago
parent
commit
0985080cf9

+ 6 - 2
panda/src/pgraph/Sources.pp

@@ -2,11 +2,12 @@
                    dtoolutil:c dtoolbase:c dtool:m
 #define LOCAL_LIBS \
     lerp event gsgbase gobj putil linmath \
-    downloader express pandabase pstatclient
+    downloader express pandabase pstatclient 
+ 
 
 #begin lib_target
   #define TARGET pgraph
-  
+
   #define SOURCES \
     accumulatedAttribs.I accumulatedAttribs.h \
     alphaTestAttrib.I alphaTestAttrib.h \  
@@ -78,6 +79,7 @@
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \
     renderState.I renderState.h \
+    seaPatchNode.h seaPatchNode.I \
     sceneGraphAnalyzer.h \
     sceneGraphReducer.I sceneGraphReducer.h \
     sceneSetup.I sceneSetup.h \
@@ -170,6 +172,7 @@
     sceneGraphAnalyzer.cxx \
     sceneGraphReducer.cxx \
     sceneSetup.cxx \
+    seaPatchNode.cxx \
     selectiveChildNode.cxx \
     sequenceNode.cxx \
     showBoundsEffect.cxx \
@@ -253,6 +256,7 @@
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \
     renderState.I renderState.h \
+    seaPatchNode.I seaPatchNode.h \
     sceneGraphAnalyzer.h \
     sceneGraphReducer.I sceneGraphReducer.h \
     sceneSetup.I sceneSetup.h \

+ 2 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -72,6 +72,7 @@
 #include "renderEffects.h"
 #include "renderModeAttrib.h"
 #include "renderState.h"
+#include "seaPatchNode.h"
 #include "selectiveChildNode.h"
 #include "sequenceNode.h"
 #include "showBoundsEffect.h"
@@ -224,6 +225,7 @@ init_libpgraph() {
   RenderEffects::init_type();
   RenderModeAttrib::init_type();
   RenderState::init_type();
+  SeaPatchNode::init_type();
   SelectiveChildNode::init_type();
   SequenceNode::init_type();
   ShowBoundsEffect::init_type();

+ 1 - 0
panda/src/pgraph/pgraph_composite2.cxx

@@ -27,6 +27,7 @@
 #include "renderEffects.cxx"
 #include "renderModeAttrib.cxx"
 #include "renderState.cxx"
+#include "seaPatchNode.cxx"
 #include "sceneGraphAnalyzer.cxx"
 #include "sceneGraphReducer.cxx"
 #include "selectiveChildNode.cxx"

+ 550 - 0
panda/src/pgraph/seaPatchNode.I

@@ -0,0 +1,550 @@
+// Filename: seaPatchNode.I
+// Created by:  sshodhan (18Jun04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::operator ==
+//       Access: Published
+//  Description: Returns true if the two lights are equivalent
+//               that is, all their properties are same
+////////////////////////////////////////////////////////////////////
+INLINE bool SeaPatchNode::
+operator == (const SeaPatchNode &other) const {
+  return (compare_to(other) == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::operator !=
+//       Access: Published
+//  Description: Returns true if the two lights are not equivalent.
+////////////////////////////////////////////////////////////////////
+INLINE bool SeaPatchNode::
+operator != (const SeaPatchNode &other) const {
+  return (compare_to(other) != 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::operator <
+//       Access: Published
+//  Description: Returns true if this SeaPatchNode sorts before the other
+//               one, false otherwise.  The sorting order of two
+//               nonequivalent SeaPatchNodes is consistent but undefined,
+//               and is useful only for storing SeaPatchNodes in a sorted
+//               container like an STL set.
+////////////////////////////////////////////////////////////////////
+INLINE bool SeaPatchNode::
+operator < (const SeaPatchNode &other) const {
+  return (compare_to(other) < 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::is_enabled
+//       Access: Published
+//  Description: Is this light is enabled/disabled?
+////////////////////////////////////////////////////////////////////
+INLINE bool SeaPatchNode::
+is_enabled() const {
+  return _enabled;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::enable
+//       Access: Published
+//  Description: Enable this light
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+enable(){
+  _enabled=true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::disable
+//       Access: Published
+//  Description: Disable this light
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+disable(){
+  _enabled=false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_amp
+//       Access: Published
+//  Description: Set Wave Amplitude
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_amp(float amplitude) {
+  _amplitude = amplitude;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_freq
+//       Access: Published
+//  Description: Set Wave Frequency
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_freq(float frequency) {
+  _frequency = frequency;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_amp
+//       Access: Published
+//  Description: Get Wave amplitude
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_amp() const {
+  return _amplitude;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_freq
+//       Access: Published
+//  Description: Get Wave frequency
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_freq() const {
+  return _frequency;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_passive_move
+//       Access: Published
+//  Description: This is the U and V speed at which textures will
+//               slide in default mode. This is kind of like an 
+//               idle cylce for the ocean water
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_passive_move(LVecBase2f UV) {
+  _passive_move = UV;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_passive_move
+//       Access: Published
+//  Description: This is the U and V speed at which textures will
+//               slide in default mode. This is kind of like an 
+//               idle cylce for the ocean water
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2f SeaPatchNode::
+get_passive_move() const {
+  return _passive_move;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_center
+//       Access: Published
+//  Description: Center for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE LPoint3f SeaPatchNode::
+get_center() const {
+  return _center;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_radius
+//       Access: Published
+//  Description: Radius for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_radius() const {
+  return _radius;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_threshold
+//       Access: Published
+//  Description: Threshold for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_threshold() const {
+  return _threshold;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_center
+//       Access: Published
+//  Description: Center for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_center(LPoint3f center) {
+  _center = center;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_radius
+//       Access: Published
+//  Description: Radius for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_radius(float r) {
+  _radius = r;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_threshold
+//       Access: Published
+//  Description: Radius for fade out effect
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_threshold(float t) {
+  _threshold = t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_noise_amp
+//       Access: Published
+//  Description: Set Noise Amplitude
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_noise_amp(float x) {
+  _noise_amp = x;
+} 
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_noise_amp
+//       Access: Published
+//  Description: Amplitude of noise
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_noise_amp() const {
+  return _noise_amp;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::enable_noise_uv
+//       Access: Published
+//  Description: Apply noise to UVs
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+enable_noise_uv() {
+  _noise_on_uv = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::disable_noise_uv
+//       Access: Published
+//  Description: Disable applying noise to UVs
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+disable_noise_uv() {
+  _noise_on_uv = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::is_noise_on_uv
+//       Access: Published
+//  Description: Check if noise is on
+////////////////////////////////////////////////////////////////////
+INLINE bool SeaPatchNode::
+is_noise_on_uv() const {
+  return _noise_on_uv;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::set_noise_f
+//       Access: Published
+//  Description: Set Noise Frequency
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_noise_f(float f) {
+  _noise_f = f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::get_noise_f
+//       Access: Published
+//  Description: Get Noise Frequency
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_noise_f() {
+  return _noise_f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::Weight
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+Weight(float t) {
+  return (2.0*fabs(t)-3.0) * t*t + 1.0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mod
+//  Description: An implementation of modulo (%) that is correct for
+//               negative numbers.
+////////////////////////////////////////////////////////////////////
+INLINE int SeaPatchNode::
+Mod(int quotient, int divisor) {
+  return (quotient >= 0) ? 
+    (quotient % divisor) :
+    (divisor-1 - ((-quotient-1) % divisor));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_xsize
+//  Description: A scale factor for x values to noise function
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_xsize(float xs) {
+  _xsize = xs;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_ysize
+//  Description: A scale factor for y values to noise function
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_ysize(float ys) {
+  _ysize = ys;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_xsize
+//  Description: A scale factor for x values to noise function
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_xsize() const {
+  return _xsize;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_ysize
+//  Description: A scale factor for y values to noise function
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_ysize() const {
+  return _ysize;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_u_scale
+//  Description: U coordinate computation scale
+//               We recompute UVs every frame based on world coords
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_u_scale(float us) {
+  _u_scale = us;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_v_scale
+//  Description: V coordinate computation scale
+//               We recompute UVs every frame based on world coords
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_v_scale(float vs) {
+  _v_scale = vs;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_u_scale
+//  Description: U coordinate computation scale
+//               We recompute UVs every frame based on world coords
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_u_scale() const {
+  return _u_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_v_scale
+//  Description: V coordinate computation scale
+//               We recompute UVs every frame based on world coords
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_v_scale() const {
+  return _v_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_height
+//  Description: Get the height of any point in the grid
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_height(float x, float y) const {
+   return ((sin(_wave_movement + (x / _wavelength[0]) ) 
+    + sin(_wave_movement + (y / _wavelength[1]))) * _amplitude);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_normal
+//  Description: return the normal to any point in the grid
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase3f SeaPatchNode::
+get_normal(float x, float y) const {
+   float h, h1, h2;
+   h = get_height(x,y);
+   h1 = get_height(x - 0.3, y + 0.2);
+   h2 = get_height(x - 0.4, y - 0.1);
+      
+   LVecBase3f a,b,N,s,a1, b1;
+   
+   a[0] = x - 0.3;
+   a[1] = y + 0.2;
+   a[2] = h1;
+   
+   b[0] = x - 0.4;
+   b[1] = y - 0.1;
+   b[2] = h2;
+   
+   s[0] = x;
+   s[1] = y;
+   s[2] = h;
+   
+   a1 = a - s;
+   b1 = b - s;
+   
+   N = cross(a1,b1);
+   
+   
+   float length = (float)sqrt(N[0]*N[0] + N[1]*N[1] + N[2]*N[2]);
+   
+   if(length == 0.0) {
+     length = 1.0;
+   }
+   
+   N[0] /= length;
+   N[1] /= length;
+   N[2] /= length;
+   
+   return N;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_cscale
+//  Description: Color scale for the vertex color... its just an 
+//               additive term
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_cscale(float cs) {
+  _color_scale = cs;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_ascale
+//  Description: Alpha scale for the vertex color... its just an 
+//               additive term
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_ascale(float as) {
+  _alpha_scale = as;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_cscale
+//  Description: Color scale for the vertex color... its just an 
+//               additive term
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_cscale() const {
+  return _color_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_ascale
+//  Description: Alpha scale for the vertex color... its just an 
+//               additive term
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_ascale() const {
+  return _alpha_scale;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_light_color
+//  Description: Vertex color has an additive light component
+//               Contributes 1/3 of the color
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_light_color(Colorf c) {
+  _light_color = c;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_light_color
+//  Description: Vertex color has an additive light component
+//               Contributes 1/3 of the color
+////////////////////////////////////////////////////////////////////
+INLINE Colorf SeaPatchNode::
+get_light_color() const {
+  return _light_color;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_u_sin_scale
+//  Description: Pass a sin wave through the UV scaling
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_u_sin_scale() const {
+  return _u_sin_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_v_sin_scale
+//  Description: Pass a sin wave through the UV scaling
+////////////////////////////////////////////////////////////////////
+INLINE float SeaPatchNode::
+get_v_sin_scale() const {
+  return _v_sin_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_u_sin_scale
+//  Description: Pass a sin wave through the UV scaling
+////////////////////////////////////////////////////////////////////
+INLINE void SeaPatchNode::
+set_u_sin_scale(float s) {
+  _u_sin_scale = s;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_u_sin_scale
+//  Description: Pass a sin wave through the UV scaling
+//////////////////////////////////////////////////////////////////// 
+INLINE void SeaPatchNode::
+set_v_sin_scale(float s) {
+  _v_sin_scale = s;
+}
+  
+  
+////////////////////////////////////////////////////////////////////
+//     Function: get_wavelength
+//  Description: Get the wavelength dividing factor
+//////////////////////////////////////////////////////////////////// 
+INLINE LVecBase2f SeaPatchNode::
+get_wavelength() const {
+  return _wavelength;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_wavelength
+//  Description: Set the wavelength dividing factor
+//////////////////////////////////////////////////////////////////// 
+INLINE void SeaPatchNode::
+set_wavelength(LVecBase2f w) {
+  _wavelength = w;
+}
+
+

+ 472 - 0
panda/src/pgraph/seaPatchNode.cxx

@@ -0,0 +1,472 @@
+// Filename: seaPatchNode.cxx
+// Created by:  sshodhan (18Jun04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+#include "config_pgraph.h"
+#include "nodePath.h"
+#include "clockObject.h"
+#include "dcast.h"
+#include "cullTraverserData.h"
+#include "cullTraverser.h"
+#include "seaPatchNode.h"
+#include "geomNode.h"
+#include "geom.h"
+
+
+#include <math.h>
+
+TypeHandle SeaPatchNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::Constructor
+//       Access: Published
+//  Description: Use SeaPatchNode() to construct a new
+//               SeaPatchNode object.
+////////////////////////////////////////////////////////////////////
+SeaPatchNode::
+SeaPatchNode(const string &name) :
+PandaNode(name)
+{
+  // center
+  LPoint3f c;
+  c[0] = 0.0;
+  c[1] = 0.0;
+  c[2] = 0.0;
+  _center = c;
+  _enabled = true;
+  // continuously increasing parameter to advance the wave
+  _wave_movement = 0.0;
+  _wavelength = 25.0;
+  _amplitude = 0.05;
+  _frequency = 0.01;
+  // from threshold -> radius the waves will fade out
+  _radius = 100.0;
+  _threshold = 80.0;
+  // sliding of UVs
+  _passive_move[0] = 0.0001;
+  _passive_move[1] = 0.0001;
+  // UV noise
+  _noise_amp = 0.001;
+  _noise_on_uv = true;
+  _noise_f = 10.0;
+  _noise_detail = 4;
+  _xsize = 256.0;
+  _ysize = 256.0;
+  _u_scale = 256.0;
+  _v_scale = 256.0;
+  _u_sin_scale = 1/100.0;
+  _v_sin_scale = 1/100.0;
+  // randomize noise tables
+  noise_init();
+  // shading
+  _alpha_scale = 1.0;
+  _color_scale = 1.0;
+  _light_color = Colorf(0.2, 0.4, 0.6, 1.0);
+  _alpha_mode = ANONE;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::has_cull_callback
+//       Access: Public, Virtual
+//  Description: Should be overridden by derived classes to return
+//               true if cull_callback() has been defined.  Otherwise,
+//               returns false to indicate cull_callback() does not
+//               need to be called for this node during the cull
+//               traversal.
+////////////////////////////////////////////////////////////////////
+bool SeaPatchNode::
+has_cull_callback() const {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::cull_callback
+//       Access: Public, Virtual
+//  Description: If has_cull_callback() returns true, this function
+//               will be called during the cull traversal to perform
+//               any additional operations that should be performed at
+//               cull time.  This may include additional manipulation
+//               of render state or additional visible/invisible
+//               decisions, or any other arbitrary operation.
+//
+//               By the time this function is called, the node has
+//               already passed the bounding-volume test for the
+//               viewing frustum, and the node's transform and state
+//               have already been applied to the indicated
+//               CullTraverserData object.
+//
+//               The return value is true if this node should be
+//               visible, or false if it should be culled.
+////////////////////////////////////////////////////////////////////
+bool SeaPatchNode::
+cull_callback(CullTraverser *trav, CullTraverserData &data) {
+
+  PandaNode *node = data.node(); // Get SeaPatchNode
+  // Get net transoformation matrix
+  LMatrix4f net_trans_mat = 
+    data._node_path.get_node_path().get_net_transform()->get_mat();
+
+  if(is_enabled()) {
+    // Go through all the children, find Geom nodes and pass waves
+    recurse_children(node,net_trans_mat);
+    // Advance the wave for all children
+    _wave_movement += _frequency; // Advance the wave
+  }
+
+  // Continue traversal
+  int num_children = node->get_num_children();
+  for(int i = 0; i < num_children; i++) {
+    CullTraverserData child_data(data, node->get_child(i));
+    trav->traverse(child_data);
+  }
+  return false;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::recurse_children
+//       Access: Published
+//  Description: Dig out the GeomNodes and do_wave on them
+////////////////////////////////////////////////////////////////////
+void SeaPatchNode::
+recurse_children(PandaNode *node, LMatrix4f net_trans_mat) {
+   
+  if (node->is_of_type(GeomNode::get_class_type())) {
+    GeomNode *geom_node = DCAST(GeomNode, node);
+    int num_geoms = geom_node->get_num_geoms();
+    for(int j =0; j < num_geoms; j++) { 
+      PT(Geom) geom = geom_node->get_geom(j);
+      do_wave(geom, net_trans_mat);
+    }
+  }
+  PandaNode::Children cr = node->get_children();
+  int num_children = cr.get_num_children();
+  for (int i = 0; i < num_children; i++) {
+    recurse_children(cr.get_child(i), net_trans_mat);
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::do_wave
+//       Access: Published
+//  Description: pass sine wave through geometry
+//               add UV noise and movement
+//               apply vertex color based shading
+////////////////////////////////////////////////////////////////////
+void SeaPatchNode::
+do_wave(Geom * geom, LMatrix4f net_trans_mat) {
+  float dist;
+  unsigned int num_vertices = geom->get_num_vertices();
+  PTA_ushort vindex;
+  PTA_ushort tindex;
+  PTA_ushort cindex;
+  PTA_ushort nindex;
+  PTA_Vertexf vert;
+  PTA_TexCoordf texc;
+  PTA_Colorf colors;
+  PTA_Normalf norms;
+  Colorf c;
+  GeomBindType btypet;
+  float u = 0.0, v = 0.0;
+  float unoise,vnoise;
+  float height_change;
+
+  // Get vertices and UVs
+  geom->get_coords(vert, vindex);
+  geom->get_texcoords(texc, btypet, tindex);
+
+  for (unsigned int k = 0; k < num_vertices; k++) { // For all vertices
+    LPoint3f V = vert[k] * net_trans_mat; // multiply with net transform
+    LPoint3f new_center = _center * net_trans_mat;
+
+    height_change = (sin(_wave_movement + (V[0] / _wavelength[0]) ) 
+    + sin(_wave_movement + (V[1] / _wavelength[1]))) * _amplitude; // Do the wave
+
+    // need this distance for fading out waves
+    // ** add fading out to getHeight function
+    dist = (float) sqrt( pow(V[0] - new_center[0],2) + pow(V[1] - new_center[1],2));
+    
+    if(dist > _threshold) {
+        if(dist >= _radius) {
+          vert[k][2] = 0.0; // completely faded out
+        }
+        else {
+          vert[k][2] = height_change * ((_radius - dist)/ _radius); // linear fade
+        }
+    }
+    else {
+      vert[k][2] = height_change;
+    }
+
+    // Recompute normals based on height
+    norms.push_back(get_normal(V[0],V[1]));
+    nindex.push_back(k);
+    geom->set_normals(norms, G_PER_VERTEX, nindex);
+
+    // Vertex color based shading
+    //  ** add shade_mode (high, low , all, none)
+    c[0] = (_color_scale + _light_color[0] + (height_change / (2 * _amplitude)))/3.0;
+    c[1] = (_color_scale + _light_color[1] + (height_change / (2 * _amplitude)))/3.0;
+    c[2] = (_color_scale + _light_color[2] + (height_change / (2 * _amplitude)))/3.0;
+    if(_alpha_mode == AHIGH) {
+      c[3] = (_alpha_scale + _light_color[3] + (1.0 - (height_change / (2 * _amplitude))))/3.0;
+    } 
+    else if(_alpha_mode == ALOW) {
+      c[3] = (_alpha_scale + _light_color[3] + (height_change / (2 * _amplitude)))/3.0;
+    }
+    else if(_alpha_mode == ATOTAL) {
+      c[3] = (_alpha_scale + _light_color[3]) /2.0;
+    }
+    else if(_alpha_mode == ANONE) {
+      c[3] = 1.0;
+    }
+
+    colors.push_back(c);
+    cindex.push_back(k);
+      
+    // UV COMPUTATION
+    // Divide vertex X and Y coords by some scale
+    // Also, pass sin wave through the scale for UV scaling
+    // ** Need to make this transform independant
+    _u_scale += sin (_wave_movement) * _u_sin_scale; 
+    _v_scale += sin (_wave_movement) * _v_sin_scale;
+
+    if(_u_scale == 0) {
+        _u_scale = 1;
+    }
+    if(_v_scale == 0) {
+        _v_scale = 1;
+    }
+
+    u = V[0]  / _u_scale;
+    v = V[1]  / _v_scale;
+
+
+    // UV Noise (using the DQ Pirates noise function)
+    if(_noise_on_uv) {
+      unoise = do_noise(V[0], V[1], ClockObject::get_global_clock()->get_frame_time(), 0);
+      vnoise = do_noise(V[0], V[1], ClockObject::get_global_clock()->get_frame_time(), 1);
+      u  +=  unoise;
+      v  +=  vnoise;
+    }
+    // Texture sliding
+    texc[k][0] = u + _move_variable[0];
+    texc[k][1] = v + _move_variable[1];
+  }
+
+  // Apply vertex shading
+  geom->set_colors (colors, G_PER_VERTEX , cindex);
+
+  _move_variable[0] += _passive_move[0];
+  _move_variable[1] += _passive_move[1];
+
+  if(_move_variable[0] > 1.0) {
+    _move_variable[0] = 0.0;
+  }
+  if(_move_variable[1] > 1.0) {
+    _move_variable[1] = 0.0;
+  }  
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: NoiseWave::Constructor
+//       Access: Public, Scheme
+//  Description: Initialize noise permutation and gradient table
+//               This function is adapted from the old DQ pirates code
+//               Everything is done for both U and V noise
+////////////////////////////////////////////////////////////////////
+void SeaPatchNode::
+noise_init() {
+
+  int i, j, k, t;
+
+  // Randomize the permutation table.
+  // U TABLE
+  for (i = 0; i < noise_table_size; i++) {
+    _perm_tab_u[i] = i;
+  }
+  for (i = 0; i < (noise_table_size / 2); i++) {
+    j = rand() % noise_table_size;
+    k = rand() % noise_table_size;
+    t = _perm_tab_u[j];
+    _perm_tab_u[j] = _perm_tab_u[k];
+    _perm_tab_u[k] = t;
+  }
+  
+
+  // Randomize the permutation table.
+  // V TABLE
+  for (i = 0; i < noise_table_size; i++) {
+    _perm_tab_v[i] = i;
+  }
+  for (i = 0; i < (noise_table_size / 2); i++) {
+    j = rand() % noise_table_size;
+    k = rand() % noise_table_size;
+    t = _perm_tab_v[j];
+    _perm_tab_v[j] = _perm_tab_v[k];
+    _perm_tab_v[k] = t;
+  }
+
+
+  // Choose a number of random unit vectors for the gradient table.
+  // U TABLE
+  for (i = 0; i < noise_table_size; i++) {
+    float m_u;
+    do {
+      _grad_tab_u[i][0] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      _grad_tab_u[i][1] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      _grad_tab_u[i][2] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      m_u = _grad_tab_u[i].dot(_grad_tab_u[i]);
+    } while (m_u == 0.0 || m_u > 1.0);
+
+    _grad_tab_u[i] /= sqrt(m_u);
+  }
+
+  // Choose a number of random unit vectors for the gradient table.
+  // V TABLE
+  for (i = 0; i < noise_table_size; i++) {
+    float m_v;
+    do {
+      _grad_tab_v[i][0] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      _grad_tab_v[i][1] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      _grad_tab_v[i][2] = (float)(rand() - (RAND_MAX / 2)) / (RAND_MAX / 2);
+      m_v = _grad_tab_v[i].dot(_grad_tab_v[i]);
+    } while (m_v == 0.0 || m_v > 1.0);
+
+    _grad_tab_v[i] /= sqrt(m_v);
+  }
+
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: NoiseWave::PlainNoise
+//       Access: Protected
+//  Description: 3D noise function 
+//               Takes x, y position , time, some scale s
+//               uvi determines if its U noise or V noise
+////////////////////////////////////////////////////////////////////
+float SeaPatchNode::
+plain_noise(float x, float y, float z, unsigned int s, int uvi ) {
+  x *= s;
+  y *= s;
+  z *= s;
+  int a = (int)floor(x);
+  int b = (int)floor(y);
+  int c = (int)floor(z);
+
+  float sum = 0.0;
+  int i, j, k;
+  for (i = 0; i < 2; i++) {
+    for (j = 0; j < 2; j++) {
+      for (k = 0; k < 2; k++) {
+        if(uvi ==0 ) {
+	      int n_u = _perm_tab_u[Mod(c + k,noise_table_size)];
+	      n_u = _perm_tab_u[Mod(b + j + n_u , noise_table_size)];
+	      n_u = _perm_tab_u[Mod(a + i + n_u , noise_table_size)];
+	      LVecBase3f v_u(x - a - i, y - b - j, z - c - k);
+	  	  sum += Weight(v_u[0]) * Weight(v_u[1]) * Weight(v_u[2]) *
+	        (_grad_tab_u[n_u].dot(v_u));
+        }
+        else {
+            int n_v = _perm_tab_v[Mod(c + k , noise_table_size)];
+	      n_v = _perm_tab_v[Mod(b + j + n_v  , noise_table_size)];
+	      n_v = _perm_tab_v[Mod(a + i + n_v , noise_table_size)];
+	      LVecBase3f v_v(x - a - i, y - b - j, z - c - k);
+	  	  sum += Weight(v_v[0]) * Weight(v_v[1]) * Weight(v_v[2]) *
+	        (_grad_tab_v[n_v].dot(v_v));
+        }
+
+      }
+    }
+  }
+
+  return sum / s;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: NoiseWave::do_noise
+//       Access: Protected
+//  Description: Based on detail additively compute various level
+//               of detail noises
+////////////////////////////////////////////////////////////////////
+float SeaPatchNode:: 
+do_noise(float x, float y, float t, int uvi) {
+ 
+  unsigned int s = 1;
+  x /= _xsize;
+  y /= _ysize;
+  t *= _noise_f * 0.1;
+  
+  float sum = 0.0;
+  int i;
+  for (i = 0; i <= _noise_detail; i++) {
+    sum += plain_noise(x, y, t, s, uvi);
+    s *= 2;
+  }
+
+  return sum * _noise_amp; 
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_alpha_mode
+//  Description: Alpha Modes are AHIGH, ALOW, ATOTAL, ANONE
+//               high and low are height based affecting high and low
+//               points respectively. total affects all vertices
+//               none is no alpha. you have to manually setTransparency
+//////////////////////////////////////////////////////////////////// 
+void SeaPatchNode::
+set_alpha_mode(Alpha_Type a) {
+  _alpha_mode = a;
+}
+
+// ** IMPLEMENT compare_to properly once API is more finalized
+
+////////////////////////////////////////////////////////////////////
+//     Function: SeaPatchNode::compare_to
+//       Access: Published
+//  Description: Returns a number less than zero if this SeaPatchNode
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+//
+//               Two SeaPatchNodes are considered equivalent if they
+//               consist of exactly the same properties
+//				 Otherwise, they are different; different
+//               SeaPatchNodes will be ranked in a consistent but
+//               undefined ordering; the ordering is useful only for
+//               placing the SeaPatchNodes in a sorted container like an
+//               STL set.
+////////////////////////////////////////////////////////////////////
+int SeaPatchNode::
+compare_to(const SeaPatchNode &other) const {
+   if (_enabled != other._enabled) {
+	return _enabled ? 1 :-1;
+   }
+   if (_wave_movement != other._wave_movement) {
+       return _wave_movement < other._wave_movement ? -1 : 1;
+   }
+  return 0;
+}
+

+ 185 - 0
panda/src/pgraph/seaPatchNode.h

@@ -0,0 +1,185 @@
+// Filename: seaPatchNode.h
+// Created by:  sshodhan (18Jun04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SEAPATCHNODE_H
+#define SEAPATCHNODE_H
+#include "pandabase.h"
+#include "luse.h"
+#include "nodePath.h"
+#include "pmap.h"
+#include "notify.h"
+#include "pandaNode.h"
+#include "geom.h"
+#include "geomNode.h"
+#include "pmap.h"
+#include "lvecBase3.h"
+
+static const int noise_table_size = 64;
+
+////////////////////////////////////////////////////////////////////
+//       Class : SeaPatchNode
+// Description : A SeaPatchNode
+//               Modeled after the old DQ SeaPatchNode
+//               Any Geometry parented to a SeaPatchNode will have
+//               - waves
+//               - UV noise and transforms
+//               - vertex color and height based shading
+// Looking to work on:
+// - multiple sine waves at different resolutions (for base waves
+// and detail waves)
+// - independant control over multiple layers parented to the same
+//   SeaPatchNode (or should this just be done through multiple 
+//   copies of the SeaPatchNode? Need to make copy constructor and =
+// - perturbing normals (bump mapping, pixel level stuff?)
+// - wakes, decals
+// - damping floating objects
+// - reflecting things like a flaming ship, torches, sun, moon
+// - tiling to make ocean
+// - offload UV manipulation to texture matrix?
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA SeaPatchNode : public PandaNode{
+
+PUBLISHED:
+
+  enum Alpha_Type {
+    AHIGH,
+    ALOW,
+    ATOTAL,
+    ANONE,
+  };
+
+  SeaPatchNode(const string &name);
+
+  INLINE void enable();
+  INLINE void disable();
+  INLINE bool is_enabled() const;
+
+  // Comparison methods
+  INLINE bool operator == (const SeaPatchNode &other) const;
+  INLINE bool operator != (const SeaPatchNode &other) const;
+  INLINE bool operator < (const SeaPatchNode &other) const;
+  int compare_to(const SeaPatchNode &other) const;
+
+  INLINE void set_amp(float amplitude);
+  INLINE void set_freq(float frequency);
+  INLINE float get_amp() const;
+  INLINE float get_freq() const;
+  INLINE LVecBase2f get_wavelength() const;
+  INLINE void set_wavelength(LVecBase2f w);
+  INLINE void set_passive_move(LVecBase2f UV);
+  INLINE LVecBase2f get_passive_move() const;
+  INLINE LPoint3f get_center() const;
+  INLINE float get_radius() const;
+  INLINE float get_threshold() const;
+  INLINE void set_center(LPoint3f center);
+  INLINE void set_radius(float r);
+  INLINE void set_threshold(float t);
+  INLINE void set_noise_amp(float x);
+  INLINE float get_noise_amp() const;
+  INLINE void enable_noise_uv();
+  INLINE void disable_noise_uv();
+  INLINE bool is_noise_on_uv() const;
+  INLINE void set_noise_f(float f);
+  INLINE float get_noise_f();
+  INLINE float Weight(float t) ;
+  INLINE int Mod(int quotient, int divisor);
+  INLINE void set_xsize(float xs);
+  INLINE void set_ysize(float ys);
+  INLINE float get_xsize() const;
+  INLINE float get_ysize() const;
+  INLINE void set_u_scale(float us);
+  INLINE void set_v_scale(float vs);
+  INLINE float get_u_scale() const;
+  INLINE float get_v_scale() const;
+  INLINE float get_height(float x, float y) const;
+  INLINE void set_cscale(float cs);
+  INLINE void set_ascale(float as);
+  INLINE float get_cscale() const;
+  INLINE float get_ascale() const;
+  INLINE LVecBase3f get_normal(float x, float y) const;
+  INLINE void set_light_color(Colorf c);
+  INLINE Colorf get_light_color() const;
+  INLINE float get_u_sin_scale() const;
+  INLINE float get_v_sin_scale() const;
+  INLINE void set_u_sin_scale(float s);
+  INLINE void set_v_sin_scale(float s);
+  void set_alpha_mode(Alpha_Type a);
+  
+
+private:
+  bool _enabled;
+  float _wave_movement;
+  float _amplitude;
+  float _frequency;
+  LVecBase2f _wavelength;
+  LVecBase2f _passive_move;
+  LVecBase2f _move_variable;
+  LPoint3f _center;
+  float _radius;
+  float _noise_amp;
+  bool _noise_on_uv;
+  float _noise_f;
+  int _perm_tab_u[noise_table_size];
+  LVecBase3f _grad_tab_u[noise_table_size];
+  int _perm_tab_v[noise_table_size];
+  LVecBase3f _grad_tab_v[noise_table_size];
+  int _noise_detail;
+  float _xsize;
+  float _ysize;
+  float _u_scale;
+  float _v_scale;
+  float _color_scale;
+  float _alpha_scale;
+  Colorf _light_color;
+  float _u_sin_scale;
+  float _v_sin_scale;
+  float _threshold;
+  Alpha_Type _alpha_mode;
+  
+public:
+  virtual bool has_cull_callback() const;
+  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
+  void recurse_children(PandaNode *node, LMatrix4f mat);
+  void do_wave(Geom *geom, LMatrix4f mat);
+  void noise_init();
+  float plain_noise(float x, float y, float z, unsigned int s, int uvi );
+  float do_noise(float x, float y, float t, int uvi);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PandaNode::init_type();
+    register_type(_type_handle, "SeaPatchNode",
+                  PandaNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "seaPatchNode.I"
+
+#endif
+
+