SeaPatchNode initial version based on DQ Pirates SeaPatchNode

This commit is contained in:
Shalin Shodhan 2004-07-07 22:04:33 +00:00
parent d392ed83a5
commit 0985080cf9
6 changed files with 1216 additions and 2 deletions

View File

@ -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 \

View File

@ -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();

View File

@ -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
panda/src/pgraph/seaPatchNode.I Executable file
View File

@ -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;
}

472
panda/src/pgraph/seaPatchNode.cxx Executable file
View File

@ -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 <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
panda/src/pgraph/seaPatchNode.h Executable file
View File

@ -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