From 0985080cf9fe7d9601150027a31f9484b19f0457 Mon Sep 17 00:00:00 2001 From: Shalin Shodhan Date: Wed, 7 Jul 2004 22:04:33 +0000 Subject: [PATCH] SeaPatchNode initial version based on DQ Pirates SeaPatchNode --- panda/src/pgraph/Sources.pp | 8 +- panda/src/pgraph/config_pgraph.cxx | 2 + panda/src/pgraph/pgraph_composite2.cxx | 1 + panda/src/pgraph/seaPatchNode.I | 550 +++++++++++++++++++++++++ panda/src/pgraph/seaPatchNode.cxx | 472 +++++++++++++++++++++ panda/src/pgraph/seaPatchNode.h | 185 +++++++++ 6 files changed, 1216 insertions(+), 2 deletions(-) create mode 100755 panda/src/pgraph/seaPatchNode.I create mode 100755 panda/src/pgraph/seaPatchNode.cxx create mode 100755 panda/src/pgraph/seaPatchNode.h diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 8411e5e894..ed36aaec4b 100644 --- a/panda/src/pgraph/Sources.pp +++ b/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 \ diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index fae054dbe7..d559402981 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/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(); diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index ba19946941..ca0b596dae 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/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" diff --git a/panda/src/pgraph/seaPatchNode.I b/panda/src/pgraph/seaPatchNode.I new file mode 100755 index 0000000000..1db01c3262 --- /dev/null +++ b/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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// 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; +} + + diff --git a/panda/src/pgraph/seaPatchNode.cxx b/panda/src/pgraph/seaPatchNode.cxx new file mode 100755 index 0000000000..b8f727d8fe --- /dev/null +++ b/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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +#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 + +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; +} + diff --git a/panda/src/pgraph/seaPatchNode.h b/panda/src/pgraph/seaPatchNode.h new file mode 100755 index 0000000000..07b9b2f25f --- /dev/null +++ b/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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#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 + +