pgraph lighting, optional offset decal implementation

This commit is contained in:
David Rose 2002-03-28 01:51:13 +00:00
parent 333bfc3050
commit 783ba052d7
60 changed files with 3490 additions and 932 deletions

View File

@ -100,7 +100,9 @@ update_viz(Node *parent) {
// Function: CollisionSolid::get_viz
// Access: Public
// Description: Returns a GeomNode that may be rendered to visualize
// the CollisionSolid.
// the CollisionSolid. This is used during the cull
// traversal to render the CollisionNodes that have been
// made visible.
////////////////////////////////////////////////////////////////////
qpGeomNode *CollisionSolid::
get_viz() {
@ -386,6 +388,7 @@ get_solid_viz_state() {
(CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
RenderModeAttrib::make(RenderModeAttrib::M_filled),
TransparencyAttrib::make(TransparencyAttrib::M_alpha));
base_state->ref(); // once more to guard against static destruction
}
if (_tangible) {
@ -393,6 +396,7 @@ get_solid_viz_state() {
if (tangible_state == (const RenderState *)NULL) {
tangible_state = base_state->add_attrib
(ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 0.5f)));
tangible_state->ref();
}
return tangible_state;
@ -401,6 +405,7 @@ get_solid_viz_state() {
if (intangible_state == (const RenderState *)NULL) {
intangible_state = base_state->add_attrib
(ColorAttrib::make_flat(Colorf(1.0f, 0.3f, 0.5f, 0.5f)));
intangible_state->ref();
}
return intangible_state;
}
@ -425,6 +430,7 @@ get_wireframe_viz_state() {
(CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
TransparencyAttrib::make(TransparencyAttrib::M_none));
base_state->ref(); // once more to guard against static destruction
}
if (_tangible) {
@ -432,6 +438,7 @@ get_wireframe_viz_state() {
if (tangible_state == (const RenderState *)NULL) {
tangible_state = base_state->add_attrib
(ColorAttrib::make_flat(Colorf(0.0f, 0.0f, 1.0f, 1.0f)));
tangible_state->ref();
}
return tangible_state;
@ -440,6 +447,7 @@ get_wireframe_viz_state() {
if (intangible_state == (const RenderState *)NULL) {
intangible_state = base_state->add_attrib
(ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 0.0f, 1.0f)));
intangible_state->ref();
}
return intangible_state;
}
@ -463,6 +471,7 @@ get_other_viz_state() {
(CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
RenderModeAttrib::make(RenderModeAttrib::M_filled),
TransparencyAttrib::make(TransparencyAttrib::M_alpha));
base_state->ref(); // once more to guard against static destruction
}
// We don't bother to make a distinction here between tangible and

View File

@ -111,6 +111,7 @@ cull_and_draw_together() {
Windows::iterator wi;
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
GraphicsWindow *win = (*wi);
win->get_gsg()->reset_frame();
win->clear();
int num_display_regions = win->get_num_display_regions();
@ -135,12 +136,13 @@ cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) {
GraphicsStateGuardian *gsg = win->get_gsg();
nassertv(gsg != (GraphicsStateGuardian *)NULL);
if (set_gsg_lens(gsg, dr)) {
PT(SceneSetup) scene_setup = setup_scene(dr->get_qpcamera(), gsg);
if (setup_gsg(gsg, scene_setup)) {
DisplayRegionStack old_dr = gsg->push_display_region(dr);
gsg->prepare_display_region();
DrawCullHandler cull_handler(gsg);
do_cull(&cull_handler, dr->get_qpcamera(), gsg);
do_cull(&cull_handler, scene_setup, gsg);
gsg->pop_display_region(old_dr);
}
@ -158,6 +160,7 @@ cull_bin_draw() {
Windows::iterator wi;
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
GraphicsWindow *win = (*wi);
win->get_gsg()->reset_frame();
win->clear();
int num_display_regions = win->get_num_display_regions();
@ -187,64 +190,64 @@ cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
cull_result = new CullResult(gsg);
}
BinCullHandler cull_handler(cull_result);
do_cull(&cull_handler, dr->get_qpcamera(), gsg);
cull_result->finish_cull();
// Save the results for next frame.
dr->_cull_result = cull_result->make_next();
// Now draw.
do_draw(cull_result, gsg, dr);
PT(SceneSetup) scene_setup = setup_scene(dr->get_qpcamera(), gsg);
if (scene_setup != (SceneSetup *)NULL) {
BinCullHandler cull_handler(cull_result);
do_cull(&cull_handler, scene_setup, gsg);
cull_result->finish_cull();
// Save the results for next frame.
dr->_cull_result = cull_result->make_next();
// Now draw.
do_draw(cull_result, scene_setup, gsg, dr);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::do_cull
// Function: GraphicsEngine::setup_scene
// Access: Private
// Description: Fires off a cull traversal using the indicated camera.
// Description: Returns a new SceneSetup object appropriate for
// rendering the scene from the indicated camera, or
// NULL if the scene should not be rendered for some
// reason.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
do_cull(CullHandler *cull_handler, const qpNodePath &camera,
GraphicsStateGuardian *gsg) {
// Statistics
PStatTimer timer(_cull_pcollector);
PT(SceneSetup) GraphicsEngine::
setup_scene(const qpNodePath &camera, GraphicsStateGuardian *gsg) {
if (camera.is_empty()) {
// No camera, no draw.
return;
return NULL;
}
qpCamera *camera_node;
DCAST_INTO_V(camera_node, camera.node());
DCAST_INTO_R(camera_node, camera.node(), NULL);
if (!camera_node->is_active()) {
// Camera inactive, no draw.
return;
return NULL;
}
Lens *lens = camera_node->get_lens();
if (lens == (Lens *)NULL) {
// No lens, no draw.
return;
return NULL;
}
qpNodePath scene = camera_node->get_scene();
if (scene.is_empty()) {
qpNodePath scene_root = camera_node->get_scene();
if (scene_root.is_empty()) {
// No scene, no draw.
return;
return NULL;
}
qpCullTraverser trav;
trav.set_cull_handler(cull_handler);
trav.set_camera_mask(camera_node->get_camera_mask());
PT(SceneSetup) scene_setup = new SceneSetup;
// We will need both the camera transform (the net transform to the
// camera from the scene) and the world transform (the camera
// transform inverse, or the net transform to the scene from the
// camera).
CPT(TransformState) camera_transform = camera.get_transform(scene);
CPT(TransformState) world_transform = scene.get_transform(camera);
CPT(TransformState) camera_transform = camera.get_transform(scene_root);
CPT(TransformState) world_transform = scene_root.get_transform(camera);
// The render transform is the same as the world transform, except
// it is converted into the GSG's internal coordinate system. This
@ -259,8 +262,31 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
render_transform = cs_transform->compose(render_transform);
}
trav.set_camera_transform(camera_transform);
trav.set_render_transform(render_transform);
scene_setup->set_scene_root(scene_root);
scene_setup->set_camera(camera_node);
scene_setup->set_lens(lens);
scene_setup->set_camera_transform(camera_transform);
scene_setup->set_render_transform(render_transform);
return scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::do_cull
// Access: Private
// Description: Fires off a cull traversal using the indicated camera.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
GraphicsStateGuardian *gsg) {
// Statistics
PStatTimer timer(_cull_pcollector);
qpCullTraverser trav;
trav.set_cull_handler(cull_handler);
trav.set_depth_offset_decals(gsg->depth_offset_decals());
trav.set_scene(scene_setup);
trav.set_camera_mask(scene_setup->get_camera()->get_camera_mask());
if (qpview_frustum_cull) {
// If we're to be performing view-frustum culling, determine the
@ -268,20 +294,20 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
// First, we have to get the current viewing frustum, which comes
// from the lens.
PT(BoundingVolume) bv = lens->make_bounds();
PT(BoundingVolume) bv = scene_setup->get_lens()->make_bounds();
if (bv != (BoundingVolume *)NULL &&
bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
// Transform it into the appropriate coordinate space.
PT(GeometricBoundingVolume) local_frustum;
local_frustum = DCAST(GeometricBoundingVolume, bv->make_copy());
local_frustum->xform(camera_transform->get_mat());
local_frustum->xform(scene_setup->get_camera_transform()->get_mat());
trav.set_view_frustum(local_frustum);
}
}
trav.traverse(scene);
trav.traverse(scene_setup->get_scene_root());
}
////////////////////////////////////////////////////////////////////
@ -290,12 +316,12 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
// Description: Draws the previously-culled scene.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
DisplayRegion *dr) {
do_draw(CullResult *cull_result, SceneSetup *scene_setup,
GraphicsStateGuardian *gsg, DisplayRegion *dr) {
// Statistics
PStatTimer timer(_draw_pcollector);
if (set_gsg_lens(gsg, dr)) {
if (setup_gsg(gsg, scene_setup)) {
DisplayRegionStack old_dr = gsg->push_display_region(dr);
gsg->prepare_display_region();
cull_result->draw();
@ -304,25 +330,21 @@ do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::set_gsg_lens
// Function: GraphicsEngine::setup_gsg
// Access: Private
// Description: Sets up the GSG to draw with the lens from the
// indicated DisplayRegion. Returns true if the lens is
// acceptable, false otherwise.
// Description: Sets up the GSG to draw the indicated scene. Returns
// true if the scene (and its lens) is acceptable, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool GraphicsEngine::
set_gsg_lens(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
const qpNodePath &camera = dr->get_qpcamera();
if (camera.is_empty()) {
// No camera, no draw.
setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup) {
if (scene_setup == (SceneSetup *)NULL) {
// No scene, no draw.
return false;
}
qpCamera *camera_node;
DCAST_INTO_R(camera_node, camera.node(), false);
Lens *lens = camera_node->get_lens();
if (lens == (Lens *)NULL) {
const Lens *lens = scene_setup->get_lens();
if (lens == (const Lens *)NULL) {
// No lens, no draw.
return false;
}
@ -335,5 +357,7 @@ set_gsg_lens(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
return false;
}
gsg->set_scene(scene_setup);
return true;
}

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "graphicsWindow.h"
#include "sceneSetup.h"
#include "pointerTo.h"
#include "pset.h"
#include "pStatCollector.h"
@ -58,12 +59,14 @@ private:
void cull_bin_draw();
void cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr);
void do_cull(CullHandler *cull_handler, const qpNodePath &camera,
PT(SceneSetup) setup_scene(const qpNodePath &camera,
GraphicsStateGuardian *gsg);
void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
GraphicsStateGuardian *gsg);
void do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
DisplayRegion *dr);
void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
GraphicsStateGuardian *gsg, DisplayRegion *dr);
bool set_gsg_lens(GraphicsStateGuardian *gsg, DisplayRegion *dr);
bool setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup);
Pipeline *_pipeline;

View File

@ -96,6 +96,28 @@ is_closed() const {
return (_win == (GraphicsWindow *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::set_scene
// Access: Public
// Description: Sets the SceneSetup object that indicates the initial
// camera position, etc. This must be called before
// traversal begins.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsStateGuardian::
set_scene(SceneSetup *scene_setup) {
_scene_setup = scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_scene
// Access: Public
// Description: Returns the SceneSetup object.
////////////////////////////////////////////////////////////////////
INLINE SceneSetup *GraphicsStateGuardian::
get_scene() const {
return _scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::set_state
// Access: Public

View File

@ -836,6 +836,17 @@ prepare_lens() {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::reset_frame
// Access: Public, Virtual
// Description: Called before each frame is rendered, to allow the
// GSG a chance to do any internal cleanup before
// beginning the frame.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
reset_frame() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::wants_normals
// Access: Public, Virtual
@ -899,15 +910,15 @@ end_decal(GeomNode *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::polygon_offset_decals
// Function: GraphicsStateGuardian::depth_offset_decals
// Access: Public, Virtual
// Description: Returns true if this GSG can implement decals using a
// PolygonOffsetAttrib, or false if that is unreliable
// DepthOffsetAttrib, or false if that is unreliable
// and the three-step rendering process should be used
// instead.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
polygon_offset_decals() {
depth_offset_decals() {
return false;
}

View File

@ -27,6 +27,7 @@
#include "lensStack.h"
#include "graphicsStateGuardianBase.h"
#include "sceneSetup.h"
#include "nodeTransition.h"
#include "nodeTransitionCache.h"
#include "luse.h"
@ -92,6 +93,9 @@ PUBLISHED:
public:
INLINE bool is_closed() const;
INLINE void set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
virtual TextureContext *prepare_texture(Texture *tex);
virtual void apply_texture(TextureContext *tc);
virtual void release_texture(TextureContext *tc);
@ -124,6 +128,7 @@ public:
INLINE void enable_normals(bool val) { _normals_enabled = val; }
virtual void reset_frame();
// These functions will be queried by the GeomIssuer to determine if
// it should issue normals, texcoords, and/or colors, based on the
@ -135,7 +140,7 @@ public:
virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib);
virtual void end_decal(GeomNode *base_geom);
virtual bool polygon_offset_decals();
virtual bool depth_offset_decals();
virtual CPT(RenderState) begin_decal_base_first();
virtual CPT(RenderState) begin_decal_nested();
virtual CPT(RenderState) begin_decal_base_second();
@ -217,6 +222,8 @@ protected:
#endif
protected:
PT(SceneSetup) _scene_setup;
class StateInfo {
public:
INLINE StateInfo(TypeHandle type);

View File

@ -4757,6 +4757,7 @@ apply_fog(Fog *fog) {
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::apply_light( PointLight* light ) {
#if 0
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
@ -4780,6 +4781,7 @@ void DXGraphicsStateGuardian::apply_light( PointLight* light ) {
alight.dvAttenuation2 = (D3DVALUE)light->get_quadratic_attenuation();
HRESULT res = scrn.pD3DDevice->SetLight(_cur_light_id, &alight);
#endif
}
////////////////////////////////////////////////////////////////////
@ -4788,6 +4790,7 @@ void DXGraphicsStateGuardian::apply_light( PointLight* light ) {
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::apply_light( DirectionalLight* light ) {
#if 0
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
@ -4815,6 +4818,7 @@ void DXGraphicsStateGuardian::apply_light( DirectionalLight* light ) {
HRESULT res = scrn.pD3DDevice->SetLight(_cur_light_id, &alight);
// scrn.pD3DDevice->LightEnable( _cur_light_id, TRUE );
// scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
#endif
}
////////////////////////////////////////////////////////////////////
@ -4823,6 +4827,7 @@ void DXGraphicsStateGuardian::apply_light( DirectionalLight* light ) {
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::apply_light( Spotlight* light ) {
#if 0
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
@ -4900,6 +4905,7 @@ void DXGraphicsStateGuardian::apply_light( Spotlight* light ) {
HRESULT res = scrn.pD3DDevice->SetLight(_cur_light_id, &alight);
#endif // WBD_GL_MODE
#endif
}
////////////////////////////////////////////////////////////////////
@ -5194,6 +5200,7 @@ issue_render_mode(const RenderModeTransition *attrib) {
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::issue_light(const LightTransition *attrib ) {
#if 0
nassertv(attrib->get_default_dir() != TD_on);
// Initialize the current ambient light total and currently enabled
@ -5285,6 +5292,7 @@ void DXGraphicsStateGuardian::issue_light(const LightTransition *attrib ) {
call_dxLightModelAmbient(_cur_ambient_light);
enable_color_material(true);
}
#endif
}
/*

View File

@ -325,6 +325,8 @@ void display_func( void ) {
void set_lighting(bool enabled) {
if (enabled) {
cerr << "lighting is no longer supported in old scene graph.\n";
/*
// Enable the lights on the initial state.
PT(LightTransition) la = new LightTransition;
la->set_on(light.p());
@ -333,6 +335,7 @@ void set_lighting(bool enabled) {
la->set_on(dlight.p());
}
render_arc->set_transition(la);
*/
} else {
// Remove the lights from the initial state.
@ -1081,6 +1084,7 @@ int framework_main(int argc, char *argv[]) {
lights = new NamedNode("lights");
new RenderRelation(cameras, lights);
/*
light = new AmbientLight( "ambient" );
dlight = new DirectionalLight( "directional" );
plight = new PointLight( "point" );
@ -1094,6 +1098,7 @@ int framework_main(int argc, char *argv[]) {
new RenderRelation( lights, plight );
new RenderRelation( lights, slight );
#endif
*/
// Turn on culling.
CullFaceTransition *cfa = new CullFaceTransition(CullFaceProperty::M_cull_clockwise);

View File

@ -65,6 +65,11 @@ bool gl_save_mipmaps = config_glgsg.GetBool("gl-save-mipmaps", false);
// variable.
bool gl_auto_normalize_lighting = config_glgsg.GetBool("auto-normalize-lighting", false);
// Configure this true to try to implement decals using a
// DepthOffsetAttrib, false to do them with the more reliable 3-pass
// rendering method instead.
bool gl_depth_offset_decals = config_glgsg.GetBool("depth-offset-decals", false);
// Configure this true to indicate the current version of GL fully
// supports textures with B, G, R ordering; false if it only supports
// R, G, B. false will always work, but true might be faster if the

View File

@ -32,6 +32,7 @@ extern bool gl_force_mipmaps;
extern bool gl_show_mipmaps;
extern bool gl_save_mipmaps;
extern bool gl_auto_normalize_lighting;
extern bool gl_depth_offset_decals;
extern bool gl_supports_bgr;
// Ways to implement decals.

View File

@ -66,6 +66,7 @@
#include "pointShapeTransition.h"
#include "polygonOffsetTransition.h"
#include "textureAttrib.h"
#include "lightAttrib.h"
#include "cullFaceAttrib.h"
#include "transparencyAttrib.h"
#include "depthTestAttrib.h"
@ -327,6 +328,9 @@ reset() {
la->issue(this);
ta->issue(this);
Material empty;
apply_material(&empty);
if (gl_cheap_textures) {
glgsg_cat.info()
<< "Setting glHint() for fastest textures.\n";
@ -1019,16 +1023,9 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
// save the modelview matrix
const LMatrix4f &modelview_mat = _transform->get_mat();
// get the camera information
// Hmm, this doesn't work any more, since we don't store the camera
// pointer in new scene graph land. Need to find a better way to
// get the current window's aspect ratio. Here's a temporary hack
// for now.
// float aspect_ratio =
// get_current_camera()->get_lens()->get_aspect_ratio();
float aspect_ratio = 1.333333;
// We don't need to mess with the aspect ratio, since we are now
// using the default projection matrix, which has the right aspect
// ratio built in.
// load up our own matrices
glMatrixMode(GL_MODELVIEW);
@ -1088,7 +1085,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
// y direction
if (y_overall)
scaled_height = geom->_y_texel_ratio[0] * half_height * aspect_ratio;
scaled_height = geom->_y_texel_ratio[0] * half_height;
else {
nassertv(((int)geom->_y_texel_ratio.size() >= geom->get_num_prims()));
y_walk = &geom->_y_texel_ratio[0];
@ -1170,7 +1167,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
scaled_width = cur_image._x_ratio * half_width;
if (y_overall == false)
scaled_height = cur_image._y_ratio * half_height * aspect_ratio;
scaled_height = cur_image._y_ratio * half_height;
// if not G_OVERALL, do some trig for this z rotate
if (theta_on) {
@ -2526,58 +2523,48 @@ apply_fog(qpFog *fog) {
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::apply_light( PointLight* light )
{
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glMatrixMode(GL_MODELVIEW)" << endl;
glgsg_cat.debug()
<< "glPushMatrix()" << endl;
glgsg_cat.debug()
<< "glLoadIdentity()" << endl;
#endif
void GLGraphicsStateGuardian::
apply_light(PointLight *light) {
// We need to temporarily load a new matrix so we can define the
// light in a known coordinate system. We pick the transform of the
// root. (Alternatively, we could leave the current transform where
// it is and compute the light position relative to that transform
// instead of relative to the root, by composing with the matrix
// computed by _transform->invert_compose(render_transform). But I
// think loading a completely new matrix is simpler.)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data());
glLoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right)
.get_data());
GLenum id = get_light_id( _cur_light_id );
Colorf black(0, 0, 0, 1);
GLenum id = get_light_id(_cur_light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
glLightfv(id, GL_AMBIENT, black.get_data());
glLightfv(id, GL_DIFFUSE, light->get_color().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
LPoint3f pos = get_rel_pos( light, _current_camera );
LPoint4f fpos( pos[0], pos[1], pos[2], 1 );
glLightfv( id, GL_POSITION, fpos.get_data() );
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
qpNodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(qpNodePath());
LPoint3f pos = light->get_point() * light_mat;
LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
glLightfv(id, GL_POSITION, fpos.get_data());
// GL_SPOT_DIRECTION is not significant when cutoff == 180
// Exponent == 0 implies uniform light distribution
glLightf( id, GL_SPOT_EXPONENT, 0 );
// Exponent == 0 implies uniform light distribution
glLightf(id, GL_SPOT_EXPONENT, 0.0f);
// Cutoff == 180 means uniform point light source
glLightf( id, GL_SPOT_CUTOFF, 180.0 );
glLightf(id, GL_SPOT_CUTOFF, 180.0f);
glLightf( id, GL_CONSTANT_ATTENUATION,
light->get_constant_attenuation() );
glLightf( id, GL_LINEAR_ATTENUATION,
light->get_linear_attenuation() );
glLightf( id, GL_QUADRATIC_ATTENUATION,
light->get_quadratic_attenuation() );
const LVecBase3f &att = light->get_attenuation();
glLightf(id, GL_CONSTANT_ATTENUATION, att[0]);
glLightf(id, GL_LINEAR_ATTENUATION, att[1]);
glLightf(id, GL_QUADRATIC_ATTENUATION, att[2]);
glPopMatrix();
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
@ -2586,56 +2573,43 @@ void GLGraphicsStateGuardian::apply_light( PointLight* light )
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::apply_light( DirectionalLight* light )
{
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glMatrixMode(GL_MODELVIEW)" << endl;
glgsg_cat.debug()
<< "glPushMatrix()" << endl;
glgsg_cat.debug()
<< "glLoadIdentity()" << endl;
#endif
void GLGraphicsStateGuardian::
apply_light(DirectionalLight *light) {
// See the comment about this transform change in PointLight, above.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right)
.get_data());
glLoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data());
GLenum id = get_light_id( _cur_light_id );
Colorf black(0, 0, 0, 1);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
glLightfv(id, GL_AMBIENT, black.get_data());
glLightfv(id, GL_DIFFUSE, light->get_color().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
// w == 0 implies light is at infinity
LPoint3f dir = get_rel_forward( light, _current_camera,
_coordinate_system );
LPoint4f pos( -dir[0], -dir[1], -dir[2], 0 );
glLightfv( id, GL_POSITION, pos.get_data() );
// Position needs to specify x, y, z, and w.
// w == 0 implies light is at infinity
qpNodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(qpNodePath());
LVector3f dir = light->get_direction() * light_mat;
LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0);
glLightfv(id, GL_POSITION, fdir.get_data());
// GL_SPOT_DIRECTION is not significant when cutoff == 180
// In this case, position x, y, z specifies direction
// Exponent == 0 implies uniform light distribution
glLightf( id, GL_SPOT_EXPONENT, 0 );
glLightf(id, GL_SPOT_EXPONENT, 0.0f);
// Cutoff == 180 means uniform point light source
glLightf( id, GL_SPOT_CUTOFF, 180.0 );
glLightf(id, GL_SPOT_CUTOFF, 180.0f);
// Default attenuation values (only spotlight can modify these)
glLightf( id, GL_CONSTANT_ATTENUATION, 1 );
glLightf( id, GL_LINEAR_ATTENUATION, 0 );
glLightf( id, GL_QUADRATIC_ATTENUATION, 0 );
// Default attenuation values (only spotlight and point light can
// modify these)
glLightf(id, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(id, GL_LINEAR_ATTENUATION, 0.0f);
glLightf(id, GL_QUADRATIC_ATTENUATION, 0.0f);
glPopMatrix();
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
@ -2644,54 +2618,42 @@ void GLGraphicsStateGuardian::apply_light( DirectionalLight* light )
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::apply_light( Spotlight* light )
{
// The light position will be relative to the current matrix, so
// we have to know what the current matrix is. Find a better
// solution later.
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glMatrixMode(GL_MODELVIEW)" << endl;
glgsg_cat.debug()
<< "glPushMatrix()" << endl;
glgsg_cat.debug()
<< "glLoadIdentity()" << endl;
#endif
void GLGraphicsStateGuardian::
apply_light(Spotlight *light) {
Lens *lens = light->get_lens();
nassertv(lens != (Lens *)NULL);
// See the comment about this transform change in PointLight, above.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right)
.get_data());
glLoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data());
GLenum id = get_light_id( _cur_light_id );
Colorf black(0, 0, 0, 1);
GLenum id = get_light_id(_cur_light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
glLightfv(id, GL_AMBIENT, black.get_data());
glLightfv(id, GL_DIFFUSE, light->get_color().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular().get_data());
glLightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
LPoint3f pos = get_rel_pos( light, _current_camera );
LPoint4f fpos( pos[0], pos[1], pos[2], 1 );
glLightfv( id, GL_POSITION, fpos.get_data() );
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
qpNodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(qpNodePath());
LPoint3f pos = lens->get_nodal_point() * light_mat;
LVector3f dir = lens->get_view_vector() * light_mat;
glLightfv( id, GL_SPOT_DIRECTION,
get_rel_forward( light, _current_camera,
_coordinate_system ).get_data() );
glLightf( id, GL_SPOT_EXPONENT, light->get_exponent() );
glLightf( id, GL_SPOT_CUTOFF,
light->get_cutoff_angle() );
glLightf( id, GL_CONSTANT_ATTENUATION,
light->get_constant_attenuation() );
glLightf( id, GL_LINEAR_ATTENUATION,
light->get_linear_attenuation() );
glLightf( id, GL_QUADRATIC_ATTENUATION,
light->get_quadratic_attenuation() );
LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
glLightfv(id, GL_POSITION, fpos.get_data());
glLightfv(id, GL_SPOT_DIRECTION, dir.get_data());
glLightf(id, GL_SPOT_EXPONENT, light->get_exponent());
glLightf(id, GL_SPOT_CUTOFF, lens->get_hfov());
const LVecBase3f &att = light->get_attenuation();
glLightf(id, GL_CONSTANT_ATTENUATION, att[0]);
glLightf(id, GL_LINEAR_ATTENUATION, att[1]);
glLightf(id, GL_QUADRATIC_ATTENUATION, att[2]);
glPopMatrix();
#ifdef GSG_VERBOSE
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
@ -2700,8 +2662,8 @@ void GLGraphicsStateGuardian::apply_light( Spotlight* light )
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::apply_light( AmbientLight* )
{
void GLGraphicsStateGuardian::
apply_light(AmbientLight *) {
// Ambient lights are handled as a special case in issue_light().
}
@ -2984,6 +2946,7 @@ issue_render_mode(const RenderModeTransition *attrib) {
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::issue_light(const LightTransition *attrib )
{
#if 0
nassertv(attrib->get_default_dir() != TD_on);
// activate();
@ -3075,6 +3038,7 @@ void GLGraphicsStateGuardian::issue_light(const LightTransition *attrib )
call_glLightModelAmbient(cur_ambient_light);
}
report_errors();
#endif
}
////////////////////////////////////////////////////////////////////
@ -3491,6 +3455,104 @@ issue_texture(const TextureAttrib *attrib) {
report_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::issue_light
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
issue_light(const LightAttrib *attrib) {
// Initialize the current ambient light total and newly enabled
// light list
Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f);
int i;
for (i = 0; i < _max_lights; i++) {
_light_info[i]._next_enabled = false;
}
int num_enabled = 0;
int num_lights = attrib->get_num_lights();
if (attrib->get_operation() == LightAttrib::O_remove) {
num_lights = 0;
}
for (int li = 0; li < num_lights; li++) {
Light *light = attrib->get_light(li);
nassertv(light != (Light *)NULL);
num_enabled++;
enable_lighting(true);
if (light->get_type() == AmbientLight::get_class_type()) {
// Ambient lights don't require specific light ids; simply add
// in the ambient contribution to the current total
cur_ambient_light += light->get_color();
} else {
// Check to see if this light has already been bound to an id
_cur_light_id = -1;
for (i = 0; i < _max_lights; i++) {
if (_light_info[i]._light == light) {
// Light has already been bound to an id, we only need to
// enable the light, not reapply it.
_cur_light_id = -2;
enable_light(i, true);
_light_info[i]._next_enabled = true;
break;
}
}
// See if there are any unbound light ids
if (_cur_light_id == -1) {
for (i = 0; i < _max_lights; i++) {
if (_light_info[i]._light == (Light *)NULL) {
_light_info[i]._light = light;
_cur_light_id = i;
break;
}
}
}
// If there were no unbound light ids, see if we can replace
// a currently unused but previously bound id
if (_cur_light_id == -1) {
for (i = 0; i < _max_lights; i++) {
if (!attrib->has_light(_light_info[i]._light)) {
_light_info[i]._light = light;
_cur_light_id = i;
break;
}
}
}
if (_cur_light_id >= 0) {
enable_light(_cur_light_id, true);
_light_info[i]._next_enabled = true;
// We need to do something different for each type of light
light->apply(this);
} else if (_cur_light_id == -1) {
glgsg_cat.error()
<< "issue_light() - failed to bind light to id" << endl;
}
}
}
// Disable all unused lights
for (i = 0; i < _max_lights; i++) {
if (!_light_info[i]._next_enabled) {
enable_light(i, false);
}
}
// If no lights were enabled, disable lighting
if (num_enabled == 0) {
enable_lighting(false);
} else {
call_glLightModelAmbient(cur_ambient_light);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::issue_material
// Access: Public, Virtual
@ -3501,6 +3563,10 @@ issue_material(const MaterialAttrib *attrib) {
const Material *material = attrib->get_material();
if (material != (const Material *)NULL) {
apply_material(material);
} else {
// Apply a default material when materials are turned off.
Material empty;
apply_material(&empty);
}
report_errors();
}
@ -3711,9 +3777,9 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) {
int offset = attrib->get_offset();
if (offset != 0) {
GLfloat newfactor = 1.0f;
GLfloat newunits = (GLfloat)offset;
glPolygonOffset(newfactor, newunits);
// The relationship between these two parameters is a little
// unclear and poorly explained in the GL man pages.
glPolygonOffset((GLfloat) -offset, (GLfloat) -offset);
enable_polygon_offset(true);
} else {
@ -3723,6 +3789,43 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) {
report_errors();
}
static CPT(RenderState)
get_unlit_state() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
state = RenderState::make(LightAttrib::make_all_off());
state->ref();
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::reset_frame
// Access: Public, Virtual
// Description: Called before each frame is rendered, to allow the
// GSG a chance to do any internal cleanup before
// beginning the frame.
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
reset_frame() {
// Undo any lighting we had enabled last frame, to force the lights
// to be reissued, in case their parameters or positions have
// changed between frames.
if (_lighting_enabled_this_frame) {
for (int i = 0; i < _max_lights; i++) {
enable_light(i, false);
_light_info[i]._light = (Light *)NULL;
}
// Also force the lighting state to unlit, so that issue_light()
// will be guaranteed to be called next frame even if we have the
// same set of light pointers we had this frame.
modify_state(get_unlit_state());
_lighting_enabled_this_frame = false;
}
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::wants_normals
// Access: Public, Virtual
@ -3888,6 +3991,19 @@ end_decal(GeomNode *base_geom) {
report_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::depth_offset_decals
// Access: Public, Virtual
// Description: Returns true if this GSG can implement decals using a
// DepthOffsetAttrib, or false if that is unreliable
// and the three-step rendering process should be used
// instead.
////////////////////////////////////////////////////////////////////
bool GLGraphicsStateGuardian::
depth_offset_decals() {
return gl_depth_offset_decals;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::get_internal_coordinate_system
// Access: Public, Virtual

View File

@ -164,7 +164,7 @@ public:
// virtual void issue_color(const ColorAttrib *attrib);
virtual void issue_tex_matrix(const TexMatrixAttrib *attrib);
virtual void issue_texture(const TextureAttrib *attrib);
// virtual void issue_light(const LightAttrib *attrib);
virtual void issue_light(const LightAttrib *attrib);
virtual void issue_material(const MaterialAttrib *attrib);
virtual void issue_render_mode(const RenderModeAttrib *attrib);
virtual void issue_texture_apply(const TextureApplyAttrib *attrib);
@ -180,12 +180,16 @@ public:
// virtual void issue_stencil(const StencilAttrib *attrib);
// virtual void issue_clip_plane(const ClipPlaneAttrib *attrib);
virtual void reset_frame();
virtual bool wants_normals(void) const;
virtual bool wants_texcoords(void) const;
virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib);
virtual void end_decal(GeomNode *base_geom);
virtual bool depth_offset_decals();
virtual CoordinateSystem get_internal_coordinate_system() const;
virtual float compute_distance_to(const LPoint3f &point) const;
@ -357,7 +361,7 @@ protected:
class LightInfo {
public:
INLINE LightInfo();
PT_Light _light;
PT(Light) _light;
bool _enabled;
bool _next_enabled;
};

View File

@ -467,6 +467,17 @@ get_up_vector() const {
return _up_vector;
}
////////////////////////////////////////////////////////////////////
// Function: Lens::get_nodal_point
// Access: Published
// Description: Returns the center point of the lens: the point from
// which the lens is viewing.
////////////////////////////////////////////////////////////////////
LPoint3f Lens::
get_nodal_point() const {
return get_view_mat().get_row3(3);
}
////////////////////////////////////////////////////////////////////
// Function: Lens::set_iod_offset
// Access: Published

View File

@ -99,6 +99,7 @@ PUBLISHED:
void set_view_vector(const LVector3f &view_vector, const LVector3f &up_vector);
const LVector3f &get_view_vector() const;
const LVector3f &get_up_vector() const;
LPoint3f get_nodal_point() const;
void set_iod_offset(float offset);
float get_iod_offset() const;

View File

@ -123,6 +123,8 @@ class LensNode;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GraphicsStateGuardianBase : public TypedReferenceCount {
public:
virtual void reset_frame()=0;
// These functions will be queried by the GeomIssuer to determine if
// it should issue normals, texcoords, and/or colors, based on the
// GSG's current state.
@ -154,11 +156,11 @@ public:
// coordinate space differently.
virtual float compute_distance_to(const LPoint3f &point) const=0;
// These are used to implement decals. If polygon_offset_decals()
// These are used to implement decals. If depth_offset_decals()
// returns true, none of the remaining functions will be called,
// since polygon offsets can be used to implement decals fully (and
// since depth offsets can be used to implement decals fully (and
// usually faster).
virtual bool polygon_offset_decals()=0;
virtual bool depth_offset_decals()=0;
virtual CPT(RenderState) begin_decal_base_first()=0;
virtual CPT(RenderState) begin_decal_nested()=0;
virtual CPT(RenderState) begin_decal_base_second()=0;

View File

@ -8,24 +8,47 @@
linmath
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
ambientLight.h config_light.h directionalLight.I \
directionalLight.h light.h \
lightTransition.I lightTransition.h pointLight.I \
pointLight.h pt_Light.h spotlight.I spotlight.h \
vector_PT_Light.h
ambientLight.I ambientLight.h \
config_light.h \
directionalLight.I directionalLight.h \
light.I light.h \
lightAttrib.I lightAttrib.h \
lightLensNode.I lightLensNode.h \
lightNode.I lightNode.h \
lightTransition.I lightTransition.h \
pointLight.I pointLight.h \
pt_Light.h \
spotlight.I spotlight.h \
vector_PT_Light.h
#define INCLUDED_SOURCES \
ambientLight.cxx config_light.cxx directionalLight.cxx light.cxx \
lightTransition.cxx pointLight.cxx \
pt_Light.cxx spotlight.cxx vector_PT_Light.cxx
ambientLight.cxx \
config_light.cxx \
directionalLight.cxx \
light.cxx \
lightAttrib.cxx \
lightLensNode.cxx \
lightNode.cxx \
lightTransition.cxx \
pointLight.cxx \
pt_Light.cxx \
spotlight.cxx \
vector_PT_Light.cxx
#define INSTALL_HEADERS \
ambientLight.h directionalLight.I directionalLight.h light.h \
ambientLight.I ambientLight.h \
directionalLight.I directionalLight.h \
light.I light.h \
lightAttrib.I lightAttrib.h \
lightLensNode.I lightLensNode.h \
lightNode.I lightNode.h \
lightNameClass.h \
lightTransition.I lightTransition.h pointLight.I pointLight.h \
pt_Light.h spotlight.I spotlight.h vector_PT_Light.h
lightTransition.I lightTransition.h \
pointLight.I pointLight.h \
pt_Light.h \
spotlight.I spotlight.h \
vector_PT_Light.h
#define IGATESCAN all

View File

@ -0,0 +1,17 @@
// Filename: ambientLight.I
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

View File

@ -15,36 +15,54 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "ambientLight.h"
#include "graphicsStateGuardian.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
#include <indent.h>
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle AmbientLight::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::Constructor
// Access:
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
AmbientLight::AmbientLight(const string& name) : NamedNode(name)
AmbientLight::
AmbientLight(const string &name) :
LightNode(name)
{
set_color(Colorf(0.2, 0.2, 0.2, 1));
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::output
// Function: AmbientLight::Copy Constructor
// Access: Protected
// Description: Do not call the copy constructor directly; instead,
// use make_copy() or copy_subgraph() to make a copy of
// a node.
////////////////////////////////////////////////////////////////////
AmbientLight::
AmbientLight(const AmbientLight &copy) :
LightNode(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::make_copy
// Access: Public, Virtual
// Description:
// Description: Returns a newly-allocated PandaNode that is a shallow
// copy of this one. It will be a different pointer,
// but its internal data may or may not be shared with
// that of the original PandaNode. No children will be
// copied.
////////////////////////////////////////////////////////////////////
void AmbientLight::
output(ostream &out) const {
NamedNode::output(out);
PandaNode *AmbientLight::
make_copy() const {
return new AmbientLight(*this);
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::write
// Access: Public, Virtual
@ -53,6 +71,70 @@ output(ostream &out) const {
void AmbientLight::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << ":\n";
indent(out, indent_level + 2) << "color " << _color << "\n";
indent(out, indent_level + 2)
<< "color " << get_color() << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::apply
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void AmbientLight::
apply(GraphicsStateGuardian *gsg) {
gsg->apply_light(this);
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// AmbientLight.
////////////////////////////////////////////////////////////////////
void AmbientLight::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void AmbientLight::
write_datagram(BamWriter *manager, Datagram &dg) {
LightNode::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type AmbientLight is encountered
// in the Bam file. It should create the AmbientLight
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *AmbientLight::
make_from_bam(const FactoryParams &params) {
AmbientLight *node = new AmbientLight("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: AmbientLight::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new AmbientLight.
////////////////////////////////////////////////////////////////////
void AmbientLight::
fillin(DatagramIterator &scan, BamReader *manager) {
LightNode::fillin(scan, manager);
}

View File

@ -15,67 +15,59 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef AMBIENTLIGHT_H
#define AMBIENTLIGHT_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <graphicsStateGuardian.h>
#include <luse.h>
#include "pmap.h"
#include <namedNode.h>
#include "light.h"
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
#include "lightNode.h"
////////////////////////////////////////////////////////////////////
// Class : AmbientLight
// Description :
// Description : A light source that seems to illuminate all points in
// space at once. This kind of light need not actually
// be part of the scene graph, since it has no meaningful
// position.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AmbientLight : public Light, public NamedNode
{
PUBLISHED:
class EXPCL_PANDA AmbientLight : public LightNode {
PUBLISHED:
AmbientLight(const string &name);
AmbientLight( const string& name = "" );
~AmbientLight( void ) { }
protected:
AmbientLight(const AmbientLight &copy);
public:
public:
virtual PandaNode *make_copy() const;
virtual void write(ostream &out, int indent_level) const;
public:
virtual void apply(GraphicsStateGuardian *gsg);
virtual void output( ostream &out ) const;
virtual void write( ostream &out, int indent_level = 0 ) const;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual void apply( GraphicsStateGuardian* gsg ) {
gsg->apply_light( this );
}
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
LightNode::init_type();
register_type(_type_handle, "AmbientLight",
LightNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type( void ) {
return _type_handle;
}
static void init_type( void ) {
Light::init_type();
NamedNode::init_type();
register_type( _type_handle, "AmbientLight",
Light::get_class_type(),
NamedNode::get_class_type() );
}
virtual TypeHandle get_type( void ) const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
virtual TypeHandle get_light_type( void ) const {
return get_class_type();
}
private:
static TypeHandle _type_handle;
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const AmbientLight &light) {
@ -83,4 +75,6 @@ INLINE ostream &operator << (ostream &out, const AmbientLight &light) {
return out;
}
#include "ambientLight.I"
#endif

View File

@ -20,6 +20,9 @@
#include "ambientLight.h"
#include "directionalLight.h"
#include "light.h"
#include "lightAttrib.h"
#include "lightLensNode.h"
#include "lightNode.h"
#include "lightTransition.h"
#include "pointLight.h"
#include "spotlight.h"
@ -33,7 +36,16 @@ ConfigureFn(config_light) {
AmbientLight::init_type();
DirectionalLight::init_type();
Light::init_type();
LightAttrib::init_type();
LightLensNode::init_type();
LightNode::init_type();
LightTransition::init_type();
PointLight::init_type();
Spotlight::init_type();
LightAttrib::register_with_read_factory();
AmbientLight::register_with_read_factory();
DirectionalLight::register_with_read_factory();
PointLight::register_with_read_factory();
Spotlight::register_with_read_factory();
}

View File

@ -16,22 +16,108 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::get_specular
// Function: DirectionalLight::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Colorf DirectionalLight::get_specular( void ) const
INLINE DirectionalLight::CData::
CData() :
_specular_color(1.0f, 1.0f, 1.0f, 1.0f),
_point(0.0f, 0.0f, 0.0f),
_direction(LVector3f::forward())
{
return _specular;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::set_specular
// Function: DirectionalLight::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void DirectionalLight::set_specular( const Colorf& color )
INLINE DirectionalLight::CData::
CData(const DirectionalLight::CData &copy) :
_specular_color(copy._specular_color),
_point(copy._point),
_direction(copy._direction)
{
_specular = color;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::get_specular_color
// Access: Public
// Description: Returns the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE const Colorf &DirectionalLight::
get_specular_color() const {
CDReader cdata(_cycler);
return cdata->_specular_color;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::set_specular_color
// Access: Public
// Description: Sets the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE void DirectionalLight::
set_specular_color(const Colorf &color) {
CDWriter cdata(_cycler);
cdata->_specular_color = color;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::get_point
// Access: Public
// Description: Returns the point in space at which the light is
// located. This is local to the coordinate space in
// which the light is assigned.
//
// This actually has no bearing on the visual effect of
// the light, since the light is rendered as if it were
// infinitely far away. This is only used to create a
// visible representation of the light.
////////////////////////////////////////////////////////////////////
INLINE const LPoint3f &DirectionalLight::
get_point() const {
CDReader cdata(_cycler);
return cdata->_point;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::set_point
// Access: Public
// Description: Sets the point in space at which the light is located.
////////////////////////////////////////////////////////////////////
INLINE void DirectionalLight::
set_point(const LPoint3f &point) {
CDWriter cdata(_cycler);
cdata->_point = point;
mark_viz_stale();
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::get_direction
// Access: Public
// Description: Returns the direction in which the light is aimed.
// This is local to the coordinate space in which the
// light is assigned.
////////////////////////////////////////////////////////////////////
INLINE const LVector3f &DirectionalLight::
get_direction() const {
CDReader cdata(_cycler);
return cdata->_direction;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::set_direction
// Access: Public
// Description: Sets the direction in which the light is aimed.
////////////////////////////////////////////////////////////////////
INLINE void DirectionalLight::
set_direction(const LVector3f &direction) {
CDWriter cdata(_cycler);
cdata->_direction = direction;
mark_viz_stale();
}

View File

@ -15,35 +15,106 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include "directionalLight.h"
#include "graphicsStateGuardian.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
#include <indent.h>
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle DirectionalLight::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::Constructor
// Access:
// Description:
////////////////////////////////////////////////////////////////////
DirectionalLight::DirectionalLight(const string& name) : NamedNode(name)
{
set_color(Colorf(1, 1, 1, 1));
set_specular(Colorf(1, 1, 1, 1));
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::output
// Function: DirectionalLight::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *DirectionalLight::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void DirectionalLight::CData::
write_datagram(BamWriter *, Datagram &dg) const {
_specular_color.write_datagram(dg);
_point.write_datagram(dg);
_direction.write_datagram(dg);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Light.
////////////////////////////////////////////////////////////////////
void DirectionalLight::CData::
fillin(DatagramIterator &scan, BamReader *) {
_specular_color.read_datagram(scan);
_point.read_datagram(scan);
_direction.read_datagram(scan);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
DirectionalLight::
DirectionalLight(const string &name) :
LightNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::Copy Constructor
// Access: Protected
// Description: Do not call the copy constructor directly; instead,
// use make_copy() or copy_subgraph() to make a copy of
// a node.
////////////////////////////////////////////////////////////////////
DirectionalLight::
DirectionalLight(const DirectionalLight &copy) :
LightNode(copy),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated PandaNode that is a shallow
// copy of this one. It will be a different pointer,
// but its internal data may or may not be shared with
// that of the original PandaNode. No children will be
// copied.
////////////////////////////////////////////////////////////////////
PandaNode *DirectionalLight::
make_copy() const {
return new DirectionalLight(*this);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::xform
// Access: Public, Virtual
// Description: Transforms the contents of this PandaNode by the
// indicated matrix, if it means anything to do so. For
// most kinds of PandaNodes, this does nothing.
////////////////////////////////////////////////////////////////////
void DirectionalLight::
output(ostream &out) const {
NamedNode::output(out);
xform(const LMatrix4f &mat) {
LightNode::xform(mat);
CDWriter cdata(_cycler);
cdata->_point = cdata->_point * mat;
cdata->_direction = cdata->_direction * mat;
mark_viz_stale();
}
////////////////////////////////////////////////////////////////////
@ -54,6 +125,76 @@ output(ostream &out) const {
void DirectionalLight::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << ":\n";
indent(out, indent_level + 2) << "color " << _color << "\n";
indent(out, indent_level + 2) << "specular " << _specular << "\n";
indent(out, indent_level + 2)
<< "color " << get_color() << "\n";
indent(out, indent_level + 2)
<< "specular color " << get_specular_color() << "\n";
indent(out, indent_level + 2)
<< "direction " << get_direction() << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::apply
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DirectionalLight::
apply(GraphicsStateGuardian *gsg) {
gsg->apply_light(this);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// DirectionalLight.
////////////////////////////////////////////////////////////////////
void DirectionalLight::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void DirectionalLight::
write_datagram(BamWriter *manager, Datagram &dg) {
LightNode::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type DirectionalLight is encountered
// in the Bam file. It should create the DirectionalLight
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *DirectionalLight::
make_from_bam(const FactoryParams &params) {
DirectionalLight *node = new DirectionalLight("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: DirectionalLight::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new DirectionalLight.
////////////////////////////////////////////////////////////////////
void DirectionalLight::
fillin(DatagramIterator &scan, BamReader *manager) {
LightNode::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}

View File

@ -15,74 +15,87 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef DIRECTIONALLIGHT_H
#define DIRECTIONALLIGHT_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <graphicsStateGuardian.h>
#include <luse.h>
#include "pmap.h"
#include <namedNode.h>
#include "light.h"
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
#include "lightNode.h"
////////////////////////////////////////////////////////////////////
// Class : DirectionalLight
// Description :
// Description : A light shining from infinitely far away in a
// particular direction, like sunlight.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DirectionalLight : public Light, public NamedNode
{
PUBLISHED:
class EXPCL_PANDA DirectionalLight : public LightNode {
PUBLISHED:
DirectionalLight(const string &name);
DirectionalLight( const string& name = "" );
~DirectionalLight( void ) { }
protected:
DirectionalLight(const DirectionalLight &copy);
INLINE Colorf get_specular( void ) const;
INLINE void set_specular( const Colorf& color );
public:
virtual PandaNode *make_copy() const;
virtual void xform(const LMatrix4f &mat);
virtual void write(ostream &out, int indent_level) const;
PUBLISHED:
INLINE const Colorf &get_specular_color() const;
INLINE void set_specular_color(const Colorf &color);
INLINE const LPoint3f &get_point() const;
INLINE void set_point(const LPoint3f &point);
INLINE const LVector3f &get_direction() const;
INLINE void set_direction(const LVector3f &direction);
public:
virtual void apply(GraphicsStateGuardian *gsg);
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
virtual void output( ostream &out ) const;
virtual void write( ostream &out, int indent_level = 0 ) const;
Colorf _specular_color;
LPoint3f _point;
LVector3f _direction;
};
virtual void apply( GraphicsStateGuardian* gsg ) {
gsg->apply_light( this );
}
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
protected:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
Colorf _specular;
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
LightNode::init_type();
register_type(_type_handle, "DirectionalLight",
LightNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type( void ) {
return _type_handle;
}
static void init_type( void ) {
Light::init_type();
NamedNode::init_type();
register_type( _type_handle, "DirectionalLight",
Light::get_class_type(),
NamedNode::get_class_type() );
}
virtual TypeHandle get_type( void ) const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
virtual TypeHandle get_light_type( void ) const {
return get_class_type();
}
private:
static TypeHandle _type_handle;
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const DirectionalLight &light) {

98
panda/src/light/light.I Normal file
View File

@ -0,0 +1,98 @@
// Filename: light.I
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Light::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Light::CData::
CData() :
_color(1.0f, 1.0f, 1.0f, 1.0f),
_viz_geom_stale(true)
{
}
////////////////////////////////////////////////////////////////////
// Function: Light::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Light::CData::
CData(const Light::CData &copy) :
_color(copy._color),
_viz_geom(copy._viz_geom),
_viz_geom_stale(copy._viz_geom_stale)
{
}
////////////////////////////////////////////////////////////////////
// Function: Light::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Light::
Light() {
}
////////////////////////////////////////////////////////////////////
// Function: Light::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Light::
Light(const Light &copy) :
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: Light::get_color
// Access: Published
// Description: Returns the basic color of the light.
////////////////////////////////////////////////////////////////////
INLINE const Colorf &Light::
get_color() const {
CDReader cdata(_cycler);
return cdata->_color;
}
////////////////////////////////////////////////////////////////////
// Function: Light::set_color
// Access: Published
// Description: Sets the basic color of the light.
////////////////////////////////////////////////////////////////////
INLINE void Light::
set_color(const Colorf &color) {
CDWriter cdata(_cycler);
cdata->_color = color;
mark_viz_stale();
}
////////////////////////////////////////////////////////////////////
// Function: Light::mark_viz_stale
// Access: Public
// Description: Indicates that the internal visualization object will
// need to be updated.
////////////////////////////////////////////////////////////////////
INLINE void Light::
mark_viz_stale() {
CDWriter cdata(_cycler);
cdata->_viz_geom_stale = true;
}

View File

@ -15,9 +15,107 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "light.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle Light::_type_handle;
////////////////////////////////////////////////////////////////////
// Static variables
// Function: Light::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TypeHandle Light::_type_handle;
CycleData *Light::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: Light::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void Light::CData::
write_datagram(BamWriter *, Datagram &dg) const {
_color.write_datagram(dg);
}
////////////////////////////////////////////////////////////////////
// Function: Light::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Light.
////////////////////////////////////////////////////////////////////
void Light::CData::
fillin(DatagramIterator &scan, BamReader *) {
_color.read_datagram(scan);
}
////////////////////////////////////////////////////////////////////
// Function: Light::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
Light::
~Light() {
}
////////////////////////////////////////////////////////////////////
// Function: Light::get_viz
// Access: Public
// Description: Returns a GeomNode that may be rendered to visualize
// the Light. This is used during the cull traversal to
// render the Lights that have been made visible.
////////////////////////////////////////////////////////////////////
qpGeomNode *Light::
get_viz() {
CDReader cdata(_cycler);
if (cdata->_viz_geom_stale) {
CDWriter cdata_w(_cycler, cdata);
cdata_w->_viz_geom = new qpGeomNode("viz");
fill_viz_geom(cdata_w->_viz_geom);
cdata_w->_viz_geom_stale = false;
}
return cdata->_viz_geom;
}
////////////////////////////////////////////////////////////////////
// Function: Light::fill_viz_geom
// Access: Protected, Virtual
// Description: Fills the indicated GeomNode up with Geoms suitable
// for rendering this light.
////////////////////////////////////////////////////////////////////
void Light::
fill_viz_geom(qpGeomNode *) {
}
////////////////////////////////////////////////////////////////////
// Function: Light::write_datagram
// Access: Protected
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void Light::
write_datagram(BamWriter *manager, Datagram &dg) {
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: Light::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Light.
////////////////////////////////////////////////////////////////////
void Light::
fillin(DatagramIterator &scan, BamReader *manager) {
manager->read_cdata(scan, _cycler);
}

View File

@ -15,63 +15,96 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef LIGHT_H
#define LIGHT_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <typedObject.h>
#include <graphicsStateGuardian.h>
#include <referenceCount.h>
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
#include "referenceCount.h"
#include "luse.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
#include "qpgeomNode.h"
class PandaNode;
class GraphicsStateGuardian;
////////////////////////////////////////////////////////////////////
// Class : Light
// Description :
// Description : The abstract interface to all kinds of lights. The
// actual light objects also inherit from PandaNode, and
// can therefore be added to the scene graph at some
// arbitrary point to define the coordinate system of
// effect.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Light : virtual public ReferenceCount
{
PUBLISHED:
class EXPCL_PANDA Light : virtual public ReferenceCount {
// We inherit from ReferenceCount instead of TypedReferenceCount so
// that LightNode does not inherit from TypedObject twice. Note
// that we also inherit virtually from ReferenceCount for the same
// reason.
PUBLISHED:
INLINE Light();
INLINE Light(const Light &copy);
virtual ~Light();
Light( void ) { _color.set(0.0, 0.0, 0.0, 1.0); }
virtual ~Light( void ) { }
virtual PandaNode *as_node()=0;
INLINE Colorf get_color(void) const { return _color; }
INLINE void set_color(const Colorf& color) { _color = color; }
INLINE const Colorf &get_color() const;
INLINE void set_color(const Colorf &color);
virtual void output(ostream &out) const=0;
virtual void write(ostream &out, int indent_level = 0) const=0;
public:
virtual void output(ostream &out) const=0;
virtual void write(ostream &out, int indent_level) const=0;
virtual void apply(GraphicsStateGuardian *gsg)=0;
public:
virtual void apply( GraphicsStateGuardian* gsg ) = 0;
qpGeomNode *get_viz();
protected:
protected:
virtual void fill_viz_geom(qpGeomNode *viz_geom);
INLINE void mark_viz_stale();
Colorf _color;
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
public:
Colorf _color;
static TypeHandle get_class_type( void ) {
return _type_handle;
}
static void init_type( void ) {
ReferenceCount::init_type();
register_type( _type_handle, "Light",
ReferenceCount::get_class_type() );
}
virtual TypeHandle get_light_type( void ) const {
return get_class_type();
}
PT(qpGeomNode) _viz_geom;
bool _viz_geom_stale;
};
private:
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
static TypeHandle _type_handle;
protected:
void write_datagram(BamWriter *manager, Datagram &dg);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ReferenceCount::init_type();
register_type(_type_handle, "Light",
ReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const Light &light) {
@ -79,4 +112,6 @@ INLINE ostream &operator << (ostream &out, const Light &light) {
return out;
}
#include "light.I"
#endif

View File

@ -0,0 +1,88 @@
// Filename: lightAttrib.I
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::Constructor
// Access: Private
// Description: Use LightAttrib::make() to construct a new
// LightAttrib object.
////////////////////////////////////////////////////////////////////
INLINE LightAttrib::
LightAttrib() {
_operation = O_set;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::get_operation
// Access: Published
// Description: Returns the basic operation type of the LightAttrib.
// If this is O_set, the lights listed here completely
// replace any lights that were already on. If this is
// O_add, the lights here are added to the set of of
// lights that were already on, and if O_remove, the
// lights here are removed from the set of lights that
// were on.
////////////////////////////////////////////////////////////////////
INLINE LightAttrib::Operation LightAttrib::
get_operation() const {
return _operation;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::get_num_lights
// Access: Published
// Description: Returns the number of lights listed in the attribute.
////////////////////////////////////////////////////////////////////
INLINE int LightAttrib::
get_num_lights() const {
return _lights.size();
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::get_light
// Access: Published
// Description: Returns the nth lights listed in the attribute.
////////////////////////////////////////////////////////////////////
INLINE Light *LightAttrib::
get_light(int n) const {
nassertr(n >= 0 && n < (int)_lights.size(), (Light *)NULL);
return _lights[n];
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::is_identity
// Access: Published
// Description: Returns true if this is an identity attrib: it does
// not change the set of lights in use.
////////////////////////////////////////////////////////////////////
INLINE bool LightAttrib::
is_identity() const {
return _operation != O_set && _lights.empty();
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::is_all_off
// Access: Published
// Description: Returns true if this attrib turns off all lights and
// turns none on.
////////////////////////////////////////////////////////////////////
INLINE bool LightAttrib::
is_all_off() const {
return _operation == O_set && _lights.empty();
}

View File

@ -0,0 +1,489 @@
// Filename: lightAttrib.cxx
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "lightAttrib.h"
#include "pandaNode.h"
#include "graphicsStateGuardianBase.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle LightAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make_all_off
// Access: Published, Static
// Description: Constructs a new LightAttrib object that turns off
// all lights (and hence disables lighting).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
make_all_off() {
LightAttrib *attrib = new LightAttrib;
attrib->_operation = O_set;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make
// Access: Published, Static
// Description: Constructs a new LightAttrib object that turns on (or
// off, according to op) the indicate light(s).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
make(LightAttrib::Operation op, Light *light) {
LightAttrib *attrib = new LightAttrib;
attrib->_operation = op;
attrib->_lights.push_back(light);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make
// Access: Published, Static
// Description: Constructs a new LightAttrib object that turns on (or
// off, according to op) the indicate light(s).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
make(LightAttrib::Operation op, Light *light1, Light *light2) {
LightAttrib *attrib = new LightAttrib;
attrib->_operation = op;
attrib->_lights.push_back(light1);
attrib->_lights.push_back(light2);
attrib->_lights.sort();
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make
// Access: Published, Static
// Description: Constructs a new LightAttrib object that turns on (or
// off, according to op) the indicate light(s).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
make(LightAttrib::Operation op, Light *light1, Light *light2,
Light *light3) {
LightAttrib *attrib = new LightAttrib;
attrib->_operation = op;
attrib->_lights.push_back(light1);
attrib->_lights.push_back(light2);
attrib->_lights.push_back(light3);
attrib->_lights.sort();
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make
// Access: Published, Static
// Description: Constructs a new LightAttrib object that turns on (or
// off, according to op) the indicate light(s).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
make(LightAttrib::Operation op, Light *light1, Light *light2,
Light *light3, Light *light4) {
LightAttrib *attrib = new LightAttrib;
attrib->_operation = op;
attrib->_lights.push_back(light1);
attrib->_lights.push_back(light2);
attrib->_lights.push_back(light3);
attrib->_lights.push_back(light4);
attrib->_lights.sort();
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::has_light
// Access: Published
// Description: Returns true if the indicated light is listed in the
// attrib, false otherwise.
////////////////////////////////////////////////////////////////////
bool LightAttrib::
has_light(Light *light) const {
return _lights.find(light) != _lights.end();
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::issue
// Access: Public, Virtual
// Description: Calls the appropriate method on the indicated GSG
// to issue the graphics commands appropriate to the
// given attribute. This is normally called
// (indirectly) only from
// GraphicsStateGuardian::set_state() or modify_state().
////////////////////////////////////////////////////////////////////
void LightAttrib::
issue(GraphicsStateGuardianBase *gsg) const {
gsg->issue_light(this);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LightAttrib::
output(ostream &out) const {
out << get_type() << ":";
if (_operation == O_set && _lights.empty()) {
out << "all off";
} else {
switch (_operation) {
case O_set:
out << "set";
break;
case O_add:
out << "add";
break;
case O_remove:
out << "remove";
break;
}
Lights::const_iterator li;
for (li = _lights.begin(); li != _lights.end(); ++li) {
Light *light = (*li);
out << " " << light->get_type();
}
}
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived LightAttrib
// types to return a unique number indicating whether
// this LightAttrib is equivalent to the other one.
//
// This should return 0 if the two LightAttrib objects
// are equivalent, a number less than zero if this one
// should be sorted before the other one, and a number
// greater than zero otherwise.
//
// This will only be called with two LightAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int LightAttrib::
compare_to_impl(const RenderAttrib *other) const {
const LightAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (_operation != ta->_operation) {
return (int)_operation - (int)ta->_operation;
}
Lights::const_iterator li = _lights.begin();
Lights::const_iterator oli = ta->_lights.begin();
while (li != _lights.end() && oli != ta->_lights.end()) {
Light *light = (*li);
Light *other_light = (*oli);
if (light != other_light) {
return light < other_light ? -1 : 1;
}
++li;
++oli;
}
if (li != _lights.end()) {
return 1;
}
if (oli != ta->_lights.end()) {
return -1;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::compose_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify how two consecutive RenderAttrib
// objects of the same type interact.
//
// This should return the result of applying the other
// RenderAttrib to a node in the scene graph below this
// RenderAttrib, which was already applied. In most
// cases, the result is the same as the other
// RenderAttrib (that is, a subsequent RenderAttrib
// completely replaces the preceding one). On the other
// hand, some kinds of RenderAttrib (for instance,
// ColorTransformAttrib) might combine in meaningful
// ways.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
compose_impl(const RenderAttrib *other) const {
const LightAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (ta->_operation == O_set) {
// If the other type is O_set, it doesn't matter what we are.
return ta;
}
if (_operation == ta->_operation) {
// If the operation types match, the composition is simply the
// union.
return do_add(ta, _operation);
} else if (ta->_operation == O_remove) {
// If the other operation type is remove, and our type is add or
// set, then remove.
return do_remove(ta, _operation);
} else if (_operation == O_remove) {
// If our type is remove, then the other one wins.
return ta;
} else {
// Otherwise, the result is the union.
return do_add(ta, _operation);
}
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::invert_compose_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify how two consecutive RenderAttrib
// objects of the same type interact.
//
// See invert_compose() and compose_impl().
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
invert_compose_impl(const RenderAttrib *other) const {
// I think in this case the other attrib always wins. Maybe this
// needs a bit more thought. It's hard to imagine that it's even
// important to compute this properly.
return other;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived LightAttrib
// types to specify what the default property for a
// LightAttrib of this type should be.
//
// This should return a newly-allocated LightAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of LightAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *LightAttrib::
make_default_impl() const {
return new LightAttrib;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::do_add
// Access: Private
// Description: Returns a new LightAttrib that represents all the
// lights of this attrib, with those of the other one
// added in.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
do_add(const LightAttrib *other, LightAttrib::Operation op) const {
Lights::const_iterator ai = _lights.begin();
Lights::const_iterator bi = other->_lights.begin();
// Create a new LightAttrib that will hold the result.
LightAttrib *new_attrib = new LightAttrib;
new_attrib->_operation = op;
back_insert_iterator<Lights> result =
back_inserter(new_attrib->_lights);
while (ai != _lights.end() && bi != other->_lights.end()) {
if ((*ai) < (*bi)) {
// Here is a light that we have in the original, which is not
// present in the secondary.
*result = *ai;
++ai;
++result;
} else if ((*bi) < (*ai)) {
// Here is a new light we have in the secondary, that was not
// present in the original.
*result = *bi;
++bi;
++result;
} else {
// Here is a light we have in both.
*result = *ai;
++ai;
++bi;
++result;
}
}
while (ai != _lights.end()) {
*result = *ai;
++ai;
++result;
}
while (bi != other->_lights.end()) {
*result = *bi;
++bi;
++result;
}
return return_new(new_attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::do_remove
// Access: Private
// Description: Returns a new LightAttrib that represents all the
// lights of this attrib, with those of the other one
// removed.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
do_remove(const LightAttrib *other, LightAttrib::Operation op) const {
Lights::const_iterator ai = _lights.begin();
Lights::const_iterator bi = other->_lights.begin();
// Create a new LightAttrib that will hold the result.
LightAttrib *new_attrib = new LightAttrib;
new_attrib->_operation = op;
back_insert_iterator<Lights> result =
back_inserter(new_attrib->_lights);
while (ai != _lights.end() && bi != other->_lights.end()) {
if ((*ai) < (*bi)) {
// Here is a light that we have in the original, which is
// not present in the secondary. Keep it.
*result = *ai;
++ai;
++result;
} else if ((*bi) < (*ai)) {
// Here is a new light we have in the secondary, that was
// not present in the original. Ignore it.
++bi;
} else {
// Here is a light we have in both. Drop it.
++ai;
++bi;
}
}
while (ai != _lights.end()) {
*result = *ai;
++ai;
++result;
}
return return_new(new_attrib);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// LightAttrib.
////////////////////////////////////////////////////////////////////
void LightAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void LightAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_int8((int)_operation);
PN_uint16 num_lights = _lights.size();
nassertv(num_lights == _lights.size());
dg.add_uint16(num_lights);
Lights::const_iterator li;
for (li = _lights.begin(); li != _lights.end(); ++li) {
Light *light = (*li);
manager->write_pointer(dg, light->as_node());
}
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int LightAttrib::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = RenderAttrib::complete_pointers(p_list, manager);
Lights::iterator li;
for (li = _lights.begin(); li != _lights.end(); ++li) {
PandaNode *node;
DCAST_INTO_R(node, p_list[pi++], pi);
(*li) = node->as_light();
}
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type LightAttrib is encountered
// in the Bam file. It should create the LightAttrib
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *LightAttrib::
make_from_bam(const FactoryParams &params) {
LightAttrib *attrib = new LightAttrib;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new LightAttrib.
////////////////////////////////////////////////////////////////////
void LightAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_operation = (Operation)scan.get_int8();
int num_lights = scan.get_uint16();
for (int i = 0; i < num_lights; i++) {
manager->read_pointer(scan);
_lights.push_back(NULL);
}
}

View File

@ -0,0 +1,116 @@
// Filename: lightAttrib.h
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef LIGHTATTRIB_H
#define LIGHTATTRIB_H
#include "pandabase.h"
#include "light.h"
#include "renderAttrib.h"
#include "ordered_vector.h"
////////////////////////////////////////////////////////////////////
// Class : LightAttrib
// Description : Indicates which set of lights should be considered
// "on" to illuminate geometry at this level and below.
// A LightAttrib can either add lights or remove lights
// from the total set of "on" lights.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LightAttrib : public RenderAttrib {
private:
INLINE LightAttrib();
PUBLISHED:
enum Operation {
O_set,
O_add,
O_remove
};
static CPT(RenderAttrib) make_all_off();
static CPT(RenderAttrib) make(Operation op,
Light *light);
static CPT(RenderAttrib) make(Operation op,
Light *light1, Light *light2);
static CPT(RenderAttrib) make(Operation op,
Light *light1, Light *light2,
Light *light3);
static CPT(RenderAttrib) make(Operation op,
Light *light1, Light *light2,
Light *light3, Light *light4);
INLINE Operation get_operation() const;
INLINE int get_num_lights() const;
INLINE Light *get_light(int n) const;
bool has_light(Light *light) const;
INLINE bool is_identity() const;
INLINE bool is_all_off() const;
public:
virtual void issue(GraphicsStateGuardianBase *gsg) const;
virtual void output(ostream &out) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
CPT(RenderAttrib) do_add(const LightAttrib *other, Operation op) const;
CPT(RenderAttrib) do_remove(const LightAttrib *other, Operation op) const;
private:
Operation _operation;
typedef ov_set< PT(Light) > Lights;
Lights _lights;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "LightAttrib",
RenderAttrib::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 "lightAttrib.I"
#endif

View File

@ -0,0 +1,17 @@
// Filename: lightLensNode.I
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,115 @@
// Filename: lightLensNode.cxx
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "lightLensNode.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle LightLensNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
LightLensNode::
LightLensNode(const string &name) :
qpLensNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
LightLensNode::
LightLensNode(const LightLensNode &copy) :
Light(copy),
qpLensNode(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::as_node
// Access: Published, Virtual
// Description: Returns the Light object upcast to a PandaNode.
////////////////////////////////////////////////////////////////////
PandaNode *LightLensNode::
as_node() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::as_light
// Access: Public, Virtual
// Description: Cross-casts the node to a Light pointer, if it is one
// of the four kinds of Light nodes, or returns NULL if
// it is not.
////////////////////////////////////////////////////////////////////
Light *LightLensNode::
as_light() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LightLensNode::
output(ostream &out) const {
qpLensNode::output(out);
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LightLensNode::
write(ostream &out, int indent_level) const {
qpLensNode::write(out, indent_level);
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void LightLensNode::
write_datagram(BamWriter *manager, Datagram &dg) {
qpLensNode::write_datagram(manager, dg);
Light::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: LightLensNode::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new LightLensNode.
////////////////////////////////////////////////////////////////////
void LightLensNode::
fillin(DatagramIterator &scan, BamReader *manager) {
qpLensNode::fillin(scan, manager);
Light::fillin(scan, manager);
}

View File

@ -0,0 +1,81 @@
// Filename: lightLensNode.h
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef LIGHTLENSNODE_H
#define LIGHTLENSNODE_H
#include "pandabase.h"
#include "light.h"
#include "qplensNode.h"
////////////////////////////////////////////////////////////////////
// Class : LightLensNode
// Description : A derivative of Light and of LensNode.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LightLensNode : public Light, public qpLensNode {
PUBLISHED:
LightLensNode(const string &name);
protected:
LightLensNode(const LightLensNode &copy);
public:
virtual PandaNode *as_node();
virtual Light *as_light();
PUBLISHED:
// We have to explicitly publish these because they resolve the
// multiple inheritance.
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
Light::init_type();
qpLensNode::init_type();
register_type(_type_handle, "LightLensNode",
Light::get_class_type(),
qpLensNode::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;
};
INLINE ostream &operator << (ostream &out, const LightLensNode &light) {
light.output(out);
return out;
}
#include "lightLensNode.I"
#endif

View File

@ -0,0 +1,17 @@
// Filename: lightNode.I
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,115 @@
// Filename: lightNode.cxx
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "lightNode.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle LightNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: LightNode::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
LightNode::
LightNode(const string &name) :
PandaNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
LightNode::
LightNode(const LightNode &copy) :
Light(copy),
PandaNode(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::as_node
// Access: Published, Virtual
// Description: Returns the Light object upcast to a PandaNode.
////////////////////////////////////////////////////////////////////
PandaNode *LightNode::
as_node() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::as_light
// Access: Public, Virtual
// Description: Cross-casts the node to a Light pointer, if it is one
// of the four kinds of Light nodes, or returns NULL if
// it is not.
////////////////////////////////////////////////////////////////////
Light *LightNode::
as_light() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LightNode::
output(ostream &out) const {
PandaNode::output(out);
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LightNode::
write(ostream &out, int indent_level) const {
PandaNode::write(out, indent_level);
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void LightNode::
write_datagram(BamWriter *manager, Datagram &dg) {
PandaNode::write_datagram(manager, dg);
Light::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: LightNode::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new LightNode.
////////////////////////////////////////////////////////////////////
void LightNode::
fillin(DatagramIterator &scan, BamReader *manager) {
PandaNode::fillin(scan, manager);
Light::fillin(scan, manager);
}

View File

@ -0,0 +1,83 @@
// Filename: lightNode.h
// Created by: drose (26Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef LIGHTNODE_H
#define LIGHTNODE_H
#include "pandabase.h"
#include "light.h"
#include "pandaNode.h"
////////////////////////////////////////////////////////////////////
// Class : LightNode
// Description : A derivative of Light and of PandaNode. All kinds of
// Light except Spotlight (which must inherit from
// LensNode instead) inherit from this class.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LightNode : public Light, public PandaNode {
PUBLISHED:
LightNode(const string &name);
protected:
LightNode(const LightNode &copy);
public:
virtual PandaNode *as_node();
virtual Light *as_light();
PUBLISHED:
// We have to explicitly publish these because they resolve the
// multiple inheritance.
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
Light::init_type();
PandaNode::init_type();
register_type(_type_handle, "LightNode",
Light::get_class_type(),
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;
};
INLINE ostream &operator << (ostream &out, const LightNode &light) {
light.output(out);
return out;
}
#include "lightNode.I"
#endif

View File

@ -1,5 +1,7 @@
#include "light.cxx"
#include "lightAttrib.cxx"
#include "lightLensNode.cxx"
#include "lightNode.cxx"
#include "lightTransition.cxx"
#include "pt_Light.cxx"
#include "vector_PT_Light.cxx"

View File

@ -1,4 +1,3 @@
#include "config_light.cxx"
#include "ambientLight.cxx"
#include "spotlight.cxx"

View File

@ -16,82 +16,106 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PointLight::get_specular
// Function: PointLight::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Colorf PointLight::get_specular( void ) const
INLINE PointLight::CData::
CData() :
_specular_color(1.0f, 1.0f, 1.0f, 1.0f),
_attenuation(1.0f, 0.0f, 0.0f),
_point(0.0f, 0.0f, 0.0f)
{
return _specular;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::set_specular
// Function: PointLight::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PointLight::set_specular( const Colorf& color )
INLINE PointLight::CData::
CData(const PointLight::CData &copy) :
_specular_color(copy._specular_color),
_attenuation(copy._attenuation),
_point(copy._point)
{
_specular = color;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::get_constant_attenuation
// Function: PointLight::get_specular_color
// Access: Public
// Description:
// Description: Returns the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE float PointLight::get_constant_attenuation( void ) const
{
return _constant_attenuation;
INLINE const Colorf &PointLight::
get_specular_color() const {
CDReader cdata(_cycler);
return cdata->_specular_color;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::set_constant_attenuation
// Function: PointLight::set_specular_color
// Access: Public
// Description:
// Description: Sets the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE void PointLight::set_constant_attenuation( float att )
{
_constant_attenuation = att;
INLINE void PointLight::
set_specular_color(const Colorf &color) {
CDWriter cdata(_cycler);
cdata->_specular_color = color;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::get_linear_attenuation
// Function: PointLight::get_attenuation
// Access: Public
// Description:
// Description: Returns the terms of the attenuation equation for the
// light. These are, in order, the constant, linear,
// and quadratic terms based on the distance from the
// point to the vertex.
////////////////////////////////////////////////////////////////////
INLINE float PointLight::get_linear_attenuation( void ) const
{
return _linear_attenuation;
INLINE const LVecBase3f &PointLight::
get_attenuation() const {
CDReader cdata(_cycler);
return cdata->_attenuation;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::set_linear_attenuation
// Function: PointLight::set_attenuation
// Access: Public
// Description:
// Description: Sets the terms of the attenuation equation for the
// light. These are, in order, the constant, linear,
// and quadratic terms based on the distance from the
// point to the vertex.
////////////////////////////////////////////////////////////////////
INLINE void PointLight::set_linear_attenuation( float att )
{
_linear_attenuation = att;
INLINE void PointLight::
set_attenuation(const LVecBase3f &attenuation) {
CDWriter cdata(_cycler);
cdata->_attenuation = attenuation;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::get_quadratic_attenuation
// Function: PointLight::get_point
// Access: Public
// Description:
// Description: Returns the point in space at which the light is
// located. This is local to the coordinate space in
// which the light is assigned.
////////////////////////////////////////////////////////////////////
INLINE float PointLight::get_quadratic_attenuation( void ) const
{
return _quadratic_attenuation;
INLINE const LPoint3f &PointLight::
get_point() const {
CDReader cdata(_cycler);
return cdata->_point;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::set_quadratic_attenuation
// Function: PointLight::set_point
// Access: Public
// Description:
// Description: Sets the point in space at which the light is located.
////////////////////////////////////////////////////////////////////
INLINE void PointLight::set_quadratic_attenuation( float att )
{
_quadratic_attenuation = att;
INLINE void PointLight::
set_point(const LPoint3f &point) {
CDWriter cdata(_cycler);
cdata->_point = point;
mark_viz_stale();
}

View File

@ -15,36 +15,105 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pointLight.h"
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
#include "pointLight.h"
#include "graphicsStateGuardian.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle PointLight::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: PointLight::Constructor
// Access:
// Description:
////////////////////////////////////////////////////////////////////
PointLight::PointLight(const string& name) : NamedNode(name)
{
set_color(Colorf(1, 1, 1, 1));
set_specular(Colorf(1, 1, 1, 1));
set_constant_attenuation(1);
set_linear_attenuation(0);
set_quadratic_attenuation(0);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::output
// Function: PointLight::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *PointLight::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void PointLight::CData::
write_datagram(BamWriter *, Datagram &dg) const {
_specular_color.write_datagram(dg);
_attenuation.write_datagram(dg);
_point.write_datagram(dg);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Light.
////////////////////////////////////////////////////////////////////
void PointLight::CData::
fillin(DatagramIterator &scan, BamReader *) {
_specular_color.read_datagram(scan);
_attenuation.read_datagram(scan);
_point.read_datagram(scan);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PointLight::
PointLight(const string &name) :
LightNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::Copy Constructor
// Access: Protected
// Description: Do not call the copy constructor directly; instead,
// use make_copy() or copy_subgraph() to make a copy of
// a node.
////////////////////////////////////////////////////////////////////
PointLight::
PointLight(const PointLight &copy) :
LightNode(copy),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated PandaNode that is a shallow
// copy of this one. It will be a different pointer,
// but its internal data may or may not be shared with
// that of the original PandaNode. No children will be
// copied.
////////////////////////////////////////////////////////////////////
PandaNode *PointLight::
make_copy() const {
return new PointLight(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::xform
// Access: Public, Virtual
// Description: Transforms the contents of this PandaNode by the
// indicated matrix, if it means anything to do so. For
// most kinds of PandaNodes, this does nothing.
////////////////////////////////////////////////////////////////////
void PointLight::
output(ostream &out) const {
NamedNode::output(out);
xform(const LMatrix4f &mat) {
LightNode::xform(mat);
CDWriter cdata(_cycler);
cdata->_point = cdata->_point * mat;
mark_viz_stale();
}
////////////////////////////////////////////////////////////////////
@ -55,9 +124,76 @@ output(ostream &out) const {
void PointLight::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << ":\n";
indent(out, indent_level + 2) << "color " << _color << "\n";
indent(out, indent_level + 2) << "specular " << _specular << "\n";
indent(out, indent_level + 2)
<< "attenuation " << _constant_attenuation << ", "
<< _linear_attenuation << ", " << _quadratic_attenuation << "\n";
<< "color " << get_color() << "\n";
indent(out, indent_level + 2)
<< "specular color " << get_specular_color() << "\n";
indent(out, indent_level + 2)
<< "attenuation " << get_attenuation() << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::apply
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void PointLight::
apply(GraphicsStateGuardian *gsg) {
gsg->apply_light(this);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// PointLight.
////////////////////////////////////////////////////////////////////
void PointLight::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void PointLight::
write_datagram(BamWriter *manager, Datagram &dg) {
LightNode::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type PointLight is encountered
// in the Bam file. It should create the PointLight
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *PointLight::
make_from_bam(const FactoryParams &params) {
PointLight *node = new PointLight("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: PointLight::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new PointLight.
////////////////////////////////////////////////////////////////////
void PointLight::
fillin(DatagramIterator &scan, BamReader *manager) {
LightNode::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}

View File

@ -15,86 +15,87 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef POINTLIGHT_H
#define POINTLIGHT_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <graphicsStateGuardian.h>
#include <luse.h>
#include "pmap.h"
#include <namedNode.h>
#include "light.h"
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
#include "lightNode.h"
////////////////////////////////////////////////////////////////////
// Class : PointLight
// Description :
// Description : A light originating from a single point in space, and
// shining in all directions.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PointLight : public Light, public NamedNode
{
PUBLISHED:
class EXPCL_PANDA PointLight : public LightNode {
PUBLISHED:
PointLight(const string &name);
PointLight( const string& name = "" );
~PointLight( void ) { }
protected:
PointLight(const PointLight &copy);
INLINE Colorf get_specular( void ) const;
INLINE void set_specular( const Colorf& color );
public:
virtual PandaNode *make_copy() const;
virtual void xform(const LMatrix4f &mat);
virtual void write(ostream &out, int indent_level) const;
INLINE float get_constant_attenuation( void ) const;
INLINE void set_constant_attenuation( float att );
INLINE float get_linear_attenuation( void ) const;
INLINE void set_linear_attenuation( float att );
INLINE float get_quadratic_attenuation( void ) const;
INLINE void set_quadratic_attenuation( float att );
PUBLISHED:
INLINE const Colorf &get_specular_color() const;
INLINE void set_specular_color(const Colorf &color);
INLINE const LVecBase3f &get_attenuation() const;
INLINE void set_attenuation(const LVecBase3f &attenuation);
INLINE const LPoint3f &get_point() const;
INLINE void set_point(const LPoint3f &point);
public:
virtual void apply(GraphicsStateGuardian *gsg);
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
virtual void output( ostream &out ) const;
virtual void write( ostream &out, int indent_level = 0 ) const;
Colorf _specular_color;
LVecBase3f _attenuation;
LPoint3f _point;
};
virtual void apply( GraphicsStateGuardian* gsg ) {
gsg->apply_light( this );
}
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
protected:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
Colorf _specular;
float _constant_attenuation;
float _linear_attenuation;
float _quadratic_attenuation;
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
LightNode::init_type();
register_type(_type_handle, "PointLight",
LightNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type( void ) {
return _type_handle;
}
static void init_type( void ) {
Light::init_type();
NamedNode::init_type();
register_type( _type_handle, "PointLight",
Light::get_class_type(),
NamedNode::get_class_type() );
}
virtual TypeHandle get_type( void ) const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
virtual TypeHandle get_light_type( void ) const {
return get_class_type();
}
private:
static TypeHandle _type_handle;
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const PointLight &light) {

View File

@ -16,102 +16,111 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_exponent
// Function: Spotlight::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float Spotlight::get_exponent( void ) const
INLINE Spotlight::CData::
CData() :
_exponent(0.0f),
_specular_color(1.0f, 1.0f, 1.0f, 1.0f),
_attenuation(1.0f, 0.0f, 0.0f)
{
return _exponent;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Spotlight::CData::
CData(const Spotlight::CData &copy) :
_exponent(copy._exponent),
_specular_color(copy._specular_color),
_attenuation(copy._attenuation)
{
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_exponent
// Access: Public
// Description: Returns the exponent that controls the amount of
// light falloff from the center of the spotlight. See
// set_exponent().
////////////////////////////////////////////////////////////////////
INLINE float Spotlight::
get_exponent() const {
CDReader cdata(_cycler);
return cdata->_exponent;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::set_exponent
// Access: Public
// Description:
// Description: Sets the exponent that controls the amount of light
// falloff from the center of the spotlight. The light
// is attenuated by the cosine of the angle between the
// direction of the light and the direction of the point
// being lighted, raised to the power of this exponent.
// Thus, higher exponents result in a more focused light
// source, regardless of the field-of-view of the lens.
////////////////////////////////////////////////////////////////////
INLINE void Spotlight::set_exponent( float exponent )
{
_exponent = exponent;
INLINE void Spotlight::
set_exponent(float exponent) {
CDWriter cdata(_cycler);
cdata->_exponent = exponent;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_specular
// Function: Spotlight::get_specular_color
// Access: Public
// Description:
// Description: Returns the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE Colorf Spotlight::get_specular( void ) const
{
return _specular;
INLINE const Colorf &Spotlight::
get_specular_color() const {
CDReader cdata(_cycler);
return cdata->_specular_color;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::set_specular
// Function: Spotlight::set_specular_color
// Access: Public
// Description:
// Description: Sets the color of specular highlights generated by
// the light.
////////////////////////////////////////////////////////////////////
INLINE void Spotlight::set_specular( const Colorf& color )
{
_specular = color;
INLINE void Spotlight::
set_specular_color(const Colorf &color) {
CDWriter cdata(_cycler);
cdata->_specular_color = color;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_constant_attenuation
// Function: Spotlight::get_attenuation
// Access: Public
// Description:
// Description: Returns the terms of the attenuation equation for the
// light. These are, in order, the constant, linear,
// and quadratic terms based on the distance from the
// point to the vertex.
////////////////////////////////////////////////////////////////////
INLINE float Spotlight::get_constant_attenuation( void ) const
{
return _constant_attenuation;
INLINE const LVecBase3f &Spotlight::
get_attenuation() const {
CDReader cdata(_cycler);
return cdata->_attenuation;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::set_constant_attenuation
// Function: Spotlight::set_attenuation
// Access: Public
// Description:
// Description: Sets the terms of the attenuation equation for the
// light. These are, in order, the constant, linear,
// and quadratic terms based on the distance from the
// point to the vertex.
////////////////////////////////////////////////////////////////////
INLINE void Spotlight::set_constant_attenuation( float att )
{
_constant_attenuation = att;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_linear_attenuation
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float Spotlight::get_linear_attenuation( void ) const
{
return _linear_attenuation;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::set_linear_attenuation
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Spotlight::set_linear_attenuation( float att )
{
_linear_attenuation = att;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_quadratic_attenuation
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float Spotlight::get_quadratic_attenuation( void ) const
{
return _quadratic_attenuation;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::set_quadratic_attenuation
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Spotlight::set_quadratic_attenuation( float att )
{
_quadratic_attenuation = att;
INLINE void Spotlight::
set_attenuation(const LVecBase3f &attenuation) {
CDWriter cdata(_cycler);
cdata->_attenuation = attenuation;
}

View File

@ -15,50 +15,124 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "spotlight.h"
#include "lightTransition.h"
#include "config_light.h"
#include "graphicsStateGuardian.h"
#include "bamWriter.h"
#include "bamReader.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "colorAttrib.h"
#include <renderRelation.h>
#include <perspectiveLens.h>
#include <texture.h>
#include <geomNode.h>
#include <geomTrifan.h>
#include <depthWriteTransition.h>
#include <transparencyTransition.h>
#include <cullFaceTransition.h>
#include <textureTransition.h>
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle Spotlight::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: Spotlight::Constructor
// Access:
// Description:
////////////////////////////////////////////////////////////////////
Spotlight::Spotlight(const string& name) : LensNode(name)
{
set_exponent(1);
set_color(Colorf(1, 1, 1, 1));
set_specular(Colorf(1, 1, 1, 1));
set_constant_attenuation(1);
set_linear_attenuation(0);
set_quadratic_attenuation(0);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::output
// Function: Spotlight::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *Spotlight::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void Spotlight::CData::
write_datagram(BamWriter *, Datagram &dg) const {
dg.add_float32(_exponent);
_specular_color.write_datagram(dg);
_attenuation.write_datagram(dg);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Light.
////////////////////////////////////////////////////////////////////
void Spotlight::CData::
fillin(DatagramIterator &scan, BamReader *) {
_exponent = scan.get_float32();
_specular_color.read_datagram(scan);
_attenuation.read_datagram(scan);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
Spotlight::
Spotlight(const string &name) :
LightLensNode(name)
{
cerr << "Creating " << *this << ", this = " << (int)this
<< " node this = " << (int)(PandaNode *)this
<< " light this = " << (int)(Light *)this
<< " bounded this = " << (int)(BoundedObject *)this << "\n";
_internal_bound.get_bound();
cerr << "got bound 1\n";
get_internal_bound();
cerr << "got bound 2\n";
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::foo
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void Spotlight::
output(ostream &out) const {
NamedNode::output(out);
foo() {
cerr << "checking bound\n";
get_internal_bound();
cerr << "done\n";
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::Copy Constructor
// Access: Protected
// Description: Do not call the copy constructor directly; instead,
// use make_copy() or copy_subgraph() to make a copy of
// a node.
////////////////////////////////////////////////////////////////////
Spotlight::
Spotlight(const Spotlight &copy) :
LightLensNode(copy),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated PandaNode that is a shallow
// copy of this one. It will be a different pointer,
// but its internal data may or may not be shared with
// that of the original PandaNode. No children will be
// copied.
////////////////////////////////////////////////////////////////////
PandaNode *Spotlight::
make_copy() const {
return new Spotlight(*this);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::xform
// Access: Public, Virtual
// Description: Transforms the contents of this PandaNode by the
// indicated matrix, if it means anything to do so. For
// most kinds of PandaNodes, this does nothing.
////////////////////////////////////////////////////////////////////
void Spotlight::
xform(const LMatrix4f &mat) {
LightLensNode::xform(mat);
mark_viz_stale();
}
////////////////////////////////////////////////////////////////////
@ -69,47 +143,53 @@ output(ostream &out) const {
void Spotlight::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << ":\n";
indent(out, indent_level + 2) << "color " << _color << "\n";
indent(out, indent_level + 2) << "specular " << _specular << "\n";
indent(out, indent_level + 2)
<< "attenuation " << _constant_attenuation << ", "
<< _linear_attenuation << ", " << _quadratic_attenuation << "\n";
indent(out, indent_level + 2) << "exponent " << _exponent << "\n";
<< "color " << get_color() << "\n";
indent(out, indent_level + 2)
<< "specular color " << get_specular_color() << "\n";
indent(out, indent_level + 2)
<< "attenuation " << get_attenuation() << "\n";
indent(out, indent_level + 2)
<< "exponent " << get_exponent() << "\n";
Lens *lens = get_lens();
if (lens != (Lens *)NULL) {
lens->write(out, indent_level + 2);
}
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_cutoff_angle
// Access:
// Function: Spotlight::apply
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
float Spotlight::get_cutoff_angle(void) const
{
Lens* proj = ((LensNode *)this)->get_lens();
float cutoff = 0;
if (proj->get_type() == PerspectiveLens::get_class_type()) {
const LVecBase2f &fov = ((PerspectiveLens *)proj)->get_fov();
cutoff = fov[0];
}
else
light_cat.error()
<< "Spotlight::get_cutoff_angle() - spotlight has a non "
<< "perspective lens!" << endl;
return cutoff;
void Spotlight::
apply(GraphicsStateGuardian *gsg) {
gsg->apply_light(this);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::make_image
// Access:
// Description:
// Access: Public
// Description: Generates an image into the indicated texture of a
// circle with a soft edge that corresponds to the
// falloff of the spotlight. This is intended to be
// used to implement projected texture spotlights; the
// image can be applied to geometry with UV's computed
// appropriate to simulate the texture's region of
// influence.
//
// Returns true if the image is successfully generated,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool Spotlight::make_image(Texture* texture, float radius)
{
bool Spotlight::
make_image(Texture *texture, float radius) {
if (texture == NULL) {
light_cat.error()
<< "Spotlight::make_image() - NULL texture" << endl;
return false;
}
PixelBuffer* pb = texture->_pbuffer;
PixelBuffer *pb = texture->_pbuffer;
int size = pb->get_xsize();
if (size == 0) {
light_cat.error()
@ -117,14 +197,13 @@ bool Spotlight::make_image(Texture* texture, float radius)
return false;
}
uchar color[3];
color[0] = (int)(_color[0] * 255.0f);
color[1] = (int)(_color[1] * 255.0f);
color[2] = (int)(_color[2] * 255.0f);
const Colorf &color = get_color();
RGBColorf scaled_color;
scaled_color[0] = (color[0] * 255.0f);
scaled_color[1] = (color[1] * 255.0f);
scaled_color[2] = (color[2] * 255.0f);
// float cutoff = get_cutoff_angle();
// float dist = 1 / (float)tan(cutoff);
// int bufsize = size * size * 3;
int half_width = (size - 2) / 2;
float dXY = 1 / (float)half_width;
float Y = dXY + dXY;
@ -144,13 +223,13 @@ bool Spotlight::make_image(Texture* texture, float radius)
intensity = 1.0f;
else if (D < 1.0f)
intensity = pow(cos((D-radius) /
(1.0f-radius) * (MathNumbers::pi_f*0.5f)), _exponent);
(1.0f-radius) * (MathNumbers::pi_f*0.5f)), get_exponent());
else
intensity = 0;
C[0] = (uchar)(intensity * color[0]);
C[1] = (uchar)(intensity * color[1]);
C[2] = (uchar)(intensity * color[2]);
C[0] = (uchar)(intensity * scaled_color[0]);
C[1] = (uchar)(intensity * scaled_color[1]);
C[2] = (uchar)(intensity * scaled_color[2]);
tx = x + half_width;
@ -173,100 +252,90 @@ bool Spotlight::make_image(Texture* texture, float radius)
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::make_geometry
// Access:
// Description:
// Function: Spotlight::fill_viz_geom
// Access: Protected, Virtual
// Description: Fills the indicated GeomNode up with Geoms suitable
// for rendering this light.
////////////////////////////////////////////////////////////////////
NamedNode* Spotlight::
make_geometry(float intensity, float length, int num_facets)
{
Colorf diffuse = _color;
diffuse[3] = intensity;
Colorf black(0.0f, 0.0f, 0.0f, intensity);
float radius = length * (float)tan(deg_2_rad(get_cutoff_angle()));
float ang_inc = 2.0f*MathNumbers::pi_f / (float)num_facets;
int num_verts = num_facets + 1;
int num_indices = num_facets + 2;
LVector3f offset(0.0f, length, 0.0f);
LPoint3f first_last_vert(radius, length, 0.0f);
PTA_Vertexf coords=PTA_Vertexf::empty_array(num_verts);
PTA_ushort vindex=PTA_ushort::empty_array(num_indices);
PTA_Colorf colors=PTA_Colorf::empty_array(2);
PTA_ushort cindex=PTA_ushort::empty_array(num_indices);
PTA_int lengths=PTA_int::empty_array(1);
lengths[0] = num_indices;
float ang = ang_inc;
LPoint3f origin(0.0f, 0.0f, 0.0f);
LVector3f x_axis(1.0f, 0.0f, 0.0f);
LVector3f z_axis(0.0f, 0.0f, 1.0f);
LPoint3f dx, dz;
float t;
coords[0] = origin;
coords[1] = first_last_vert;
vindex[0] = 0;
vindex[1] = 1;
vindex[num_indices-1] = 1;
int i;
for (i = 2; i < num_indices-1; i++) {
float sine,cosine;
csincos(ang,&sine,&cosine);
t = cosine * radius;
dx = x_axis * t;
t = sine * radius;
dz = z_axis * t;
coords[i] = dx + dz + offset;
ang += ang_inc;
vindex[i] = i;
void Spotlight::
fill_viz_geom(qpGeomNode *viz_geom) {
Lens *lens = get_lens();
if (lens == (Lens *)NULL) {
return;
}
PT(Geom) geom = lens->make_geometry();
if (geom == (Geom *)NULL) {
return;
}
colors[0] = diffuse;
colors[1] = black;
cindex[0] = 0;
for (i = 1; i < num_indices; i++)
cindex[i] = 1;
GeomTrifan* tfan = new GeomTrifan;
tfan->set_coords(coords, vindex);
tfan->set_colors(colors, G_PER_VERTEX, cindex);
tfan->set_num_prims(1);
tfan->set_lengths(lengths);
GeomNode* geomnode = new GeomNode("spotlight_frustum_geom");
geomnode->add_geom(tfan);
NamedNode* root = new NamedNode("spotlight_frustum");
RenderRelation* root_arc = new RenderRelation(root, geomnode);
// Disable lighting
LightTransition *light_trans =
new LightTransition(LightTransition::all_off());
root_arc->set_transition(light_trans);
// Disable texturing
TextureTransition *tex_trans =
new TextureTransition(TextureTransition::off());
root_arc->set_transition(tex_trans);
// Turn off writes to Z
DepthWriteTransition *depth_trans =
new DepthWriteTransition(DepthWriteTransition::off());
root_arc->set_transition(depth_trans);
// Enable transparency
TransparencyTransition *col_trans =
new TransparencyTransition(TransparencyProperty::M_alpha);
root_arc->set_transition(col_trans);
// Disable culling
CullFaceTransition *cull_trans =
new CullFaceTransition(CullFaceProperty::M_cull_none);
root_arc->set_transition(cull_trans);
return root;
viz_geom->add_geom(geom, get_viz_state());
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::get_viz_state
// Access: Private
// Description: Returns a RenderState for rendering the spotlight
// visualization.
////////////////////////////////////////////////////////////////////
CPT(RenderState) Spotlight::
get_viz_state() {
return RenderState::make
(ColorAttrib::make_flat(get_color()));
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// Spotlight.
////////////////////////////////////////////////////////////////////
void Spotlight::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void Spotlight::
write_datagram(BamWriter *manager, Datagram &dg) {
LightLensNode::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type Spotlight is encountered
// in the Bam file. It should create the Spotlight
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *Spotlight::
make_from_bam(const FactoryParams &params) {
Spotlight *node = new Spotlight("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: Spotlight::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new Spotlight.
////////////////////////////////////////////////////////////////////
void Spotlight::
fillin(DatagramIterator &scan, BamReader *manager) {
LightLensNode::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}

View File

@ -15,98 +15,105 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef SPOTLIGHT_H
#define SPOTLIGHT_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <graphicsStateGuardian.h>
#include <luse.h>
#include "pmap.h"
#include <namedNode.h>
#include <frustum.h>
#include "light.h"
#include <lensNode.h>
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
#include "lightLensNode.h"
////////////////////////////////////////////////////////////////////
// Class : Spotlight
// Description :
// Description : A light originating from a single point in space, and
// shining in a particular direction, with a cone-shaped
// falloff.
//
// The Spotlight frustum is defined using a Lens, so it
// can have any of the properties that a camera lens can
// have.
//
// Note that the class is named Spotlight instead of
// SpotLight, because "spotlight" is a single English
// word, instead of two words.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Spotlight : public Light, public LensNode
{
PUBLISHED:
class EXPCL_PANDA Spotlight : public LightLensNode {
PUBLISHED:
Spotlight(const string &name);
void foo();
Spotlight( const string& name = "" );
~Spotlight( void ) { }
protected:
Spotlight(const Spotlight &copy);
INLINE float get_exponent( void ) const;
INLINE void set_exponent( float exponent );
public:
virtual PandaNode *make_copy() const;
virtual void xform(const LMatrix4f &mat);
virtual void write(ostream &out, int indent_level) const;
float get_cutoff_angle( void ) const;
PUBLISHED:
INLINE float get_exponent() const;
INLINE void set_exponent(float exponent);
INLINE const Colorf &get_specular_color() const;
INLINE void set_specular_color(const Colorf &color);
INLINE const LVecBase3f &get_attenuation() const;
INLINE void set_attenuation(const LVecBase3f &attenuation);
public:
virtual void apply(GraphicsStateGuardian *gsg);
INLINE Colorf get_specular( void ) const;
INLINE void set_specular( const Colorf& color );
bool make_image(Texture *texture, float radius);
INLINE float get_constant_attenuation( void ) const;
INLINE void set_constant_attenuation( float att );
protected:
virtual void fill_viz_geom(qpGeomNode *viz_geom);
INLINE float get_linear_attenuation( void ) const;
INLINE void set_linear_attenuation( float att );
INLINE float get_quadratic_attenuation( void ) const;
INLINE void set_quadratic_attenuation( float att );
private:
CPT(RenderState) get_viz_state();
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
virtual void output( ostream &out ) const;
virtual void write( ostream &out, int indent_level = 0 ) const;
float _exponent;
Colorf _specular_color;
LVecBase3f _attenuation;
};
virtual void apply( GraphicsStateGuardian* gsg ) {
gsg->apply_light( this );
}
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
bool make_image(Texture* texture, float radius = 0.7);
NamedNode* make_geometry(float intensity = 0.05, float length = 20.0,
int num_facets = 36);
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
float _exponent;
Colorf _specular;
float _constant_attenuation;
float _linear_attenuation;
float _quadratic_attenuation;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
LightLensNode::init_type();
register_type(_type_handle, "Spotlight",
LightLensNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
public:
static TypeHandle get_class_type( void ) {
return _type_handle;
}
static void init_type( void ) {
Light::init_type();
LensNode::init_type();
register_type( _type_handle, "Spotlight",
Light::get_class_type(),
LensNode::get_class_type() );
}
virtual TypeHandle get_type( void ) const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
virtual TypeHandle get_light_type( void ) const {
return get_class_type();
}
private:
static TypeHandle _type_handle;
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const Spotlight &light) {

View File

@ -52,6 +52,7 @@
renderModeAttrib.I renderModeAttrib.h \
renderState.I renderState.h \
qpsceneGraphReducer.I qpsceneGraphReducer.h \
sceneSetup.I sceneSetup.h \
selectiveChildNode.I selectiveChildNode.h \
qpsequenceNode.I qpsequenceNode.h \
showBoundsEffect.I showBoundsEffect.h \
@ -111,6 +112,7 @@
renderModeAttrib.cxx \
renderState.cxx \
qpsceneGraphReducer.cxx \
sceneSetup.cxx \
selectiveChildNode.cxx \
qpsequenceNode.cxx \
showBoundsEffect.cxx \
@ -172,6 +174,7 @@
renderModeAttrib.I renderModeAttrib.h \
renderState.I renderState.h \
qpsceneGraphReducer.I qpsceneGraphReducer.h \
sceneSetup.I sceneSetup.h \
selectiveChildNode.I selectiveChildNode.h \
qpsequenceNode.I qpsequenceNode.h \
showBoundsEffect.I showBoundsEffect.h \

View File

@ -29,11 +29,9 @@
// Description:
////////////////////////////////////////////////////////////////////
CullHandler::
~CullHandler()
{
~CullHandler() {
}
////////////////////////////////////////////////////////////////////
// Function: CullHandler::record_object
// Access: Public, Virtual

View File

@ -157,6 +157,7 @@ get_fake_view_frustum_cull_state() {
TextureAttrib::make_off(),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
1000);
state->ref(); // once more to guard against static destruction
}
return state;
}

View File

@ -1143,6 +1143,18 @@ is_geom_node() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::as_light
// Access: Public, Virtual
// Description: Cross-casts the node to a Light pointer, if it is one
// of the four kinds of Light nodes, or returns NULL if
// it is not.
////////////////////////////////////////////////////////////////////
Light *PandaNode::
as_light() {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::propagate_stale_bound
// Access: Protected, Virtual
@ -1244,7 +1256,8 @@ recompute_bound() {
////////////////////////////////////////////////////////////////////
BoundingVolume *PandaNode::
recompute_internal_bound() {
return _internal_bound.recompute_bound();
BoundingVolume *result = _internal_bound.recompute_bound();
return result;
}
////////////////////////////////////////////////////////////////////

View File

@ -43,6 +43,7 @@
class qpNodePathComponent;
class qpCullTraverser;
class CullTraverserData;
class Light;
////////////////////////////////////////////////////////////////////
// Class : PandaNode
@ -163,6 +164,7 @@ PUBLISHED:
public:
virtual bool is_geom_node() const;
virtual Light *as_light();
protected:
// Inherited from BoundedObject

View File

@ -17,6 +17,59 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_scene
// Access: Public
// Description: Sets the SceneSetup object that indicates the initial
// camera position, etc. This must be called before
// traversal begins.
////////////////////////////////////////////////////////////////////
INLINE void qpCullTraverser::
set_scene(SceneSetup *scene_setup) {
_scene_setup = scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_scene
// Access: Public
// Description: Returns the SceneSetup object.
////////////////////////////////////////////////////////////////////
INLINE SceneSetup *qpCullTraverser::
get_scene() const {
return _scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_camera_transform
// Access: Public
// Description: Returns the position of the camera relative to the
// starting node, without any compensating
// coordinate-system transforms that might have been
// introduced for the purposes of rendering.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *qpCullTraverser::
get_camera_transform() const {
return _scene_setup->get_camera_transform();
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_render_transform
// Access: Public
// Description: Returns the position of the starting node relative
// to the camera, pretransformed as appropriate for
// rendering.
//
// Note that this value is always the position of the
// starting node, not the current node, even if it is
// sampled during a traversal. To get the render
// transform of the current node check in the current
// CullTraverserData.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *qpCullTraverser::
get_render_transform() const {
return _scene_setup->get_render_transform();
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_initial_state
// Access: Public
@ -41,6 +94,31 @@ get_initial_state() const {
return _initial_state;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_depth_offset_decals
// Access: Public
// Description: Sets the depth_offset_decals flag. If this is true,
// decals will be rendered using DepthOffsetAttribs;
// otherwise, decals will be rendered with a more
// expensive three-pass system. This is normally set
// from the corresponding flag in the GSG.
////////////////////////////////////////////////////////////////////
INLINE void qpCullTraverser::
set_depth_offset_decals(bool flag) {
_depth_offset_decals = flag;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_depth_offset_decals
// Access: Public
// Description: Returns the depth_offset_decals flag. See
// set_depth_offset_decals().
////////////////////////////////////////////////////////////////////
INLINE bool qpCullTraverser::
get_depth_offset_decals() const {
return _depth_offset_decals;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_camera_mask
// Access: Public
@ -64,62 +142,6 @@ get_camera_mask() const {
return _camera_mask;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_camera_transform
// Access: Public
// Description: Specifies the position of the camera relative to the
// starting node, without any compensating
// coordinate-system transforms that might have been
// introduced for the purposes of rendering.
////////////////////////////////////////////////////////////////////
INLINE void qpCullTraverser::
set_camera_transform(const TransformState *camera_transform) {
_camera_transform = camera_transform;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_camera_transform
// Access: Public
// Description: Returns the position of the camera relative to the
// starting node, without any compensating
// coordinate-system transforms that might have been
// introduced for the purposes of rendering.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *qpCullTraverser::
get_camera_transform() const {
return _camera_transform;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_render_transform
// Access: Public
// Description: Specifies the position of the starting node relative
// to the camera, pretransformed as appropriate for
// rendering.
////////////////////////////////////////////////////////////////////
INLINE void qpCullTraverser::
set_render_transform(const TransformState *render_transform) {
_render_transform = render_transform;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_render_transform
// Access: Public
// Description: Returns the position of the starting node relative
// to the camera, pretransformed as appropriate for
// rendering.
//
// Note that this value is always the position of the
// starting node, not the current node, even if it is
// sampled during a traversal. To get the render
// transform of the current node check in the current
// CullTraverserData.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *qpCullTraverser::
get_render_transform() const {
return _render_transform;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_view_frustum
// Access: Public

View File

@ -30,6 +30,7 @@
#include "colorAttrib.h"
#include "renderModeAttrib.h"
#include "cullFaceAttrib.h"
#include "depthOffsetAttrib.h"
TypeHandle qpCullTraverser::_type_handle;
@ -42,9 +43,7 @@ TypeHandle qpCullTraverser::_type_handle;
qpCullTraverser::
qpCullTraverser() {
_initial_state = RenderState::make_empty();
_camera_mask = DrawMask::all_on();
_camera_transform = DCAST(TransformState, TransformState::make_identity());
_render_transform = DCAST(TransformState, TransformState::make_identity());
_depth_offset_decals = false;
_cull_handler = (CullHandler *)NULL;
}
@ -55,10 +54,9 @@ qpCullTraverser() {
////////////////////////////////////////////////////////////////////
qpCullTraverser::
qpCullTraverser(const qpCullTraverser &copy) :
_scene_setup(copy._scene_setup),
_initial_state(copy._initial_state),
_camera_mask(copy._camera_mask),
_camera_transform(copy._camera_transform),
_render_transform(copy._render_transform),
_depth_offset_decals(copy._depth_offset_decals),
_view_frustum(copy._view_frustum),
_guard_band(copy._guard_band),
_cull_handler(copy._cull_handler)
@ -71,11 +69,12 @@ qpCullTraverser(const qpCullTraverser &copy) :
// Description: Begins the traversal from the indicated node.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
traverse(qpNodePath &root) {
traverse(const qpNodePath &root) {
nassertv(_cull_handler != (CullHandler *)NULL);
CullTraverserData data(root,
_render_transform, TransformState::make_identity(),
nassertv(_scene_setup != (SceneSetup *)NULL);
CullTraverserData data(root, get_render_transform(),
TransformState::make_identity(),
_initial_state, _view_frustum, _guard_band);
traverse(data);
}
@ -112,7 +111,7 @@ traverse(CullTraverserData &data) {
// now. This maybe isn't the perfect time to call it, but it's
// good enough; and at this time we have all the information we
// need for it.
fog->get_fog()->adjust_to_camera(_camera_transform);
fog->get_fog()->adjust_to_camera(get_camera_transform());
}
if (node->has_cull_callback()) {
@ -133,10 +132,13 @@ traverse(CullTraverserData &data) {
// node's space.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
traverse_below(const CullTraverserData &data) {
traverse_below(CullTraverserData &data) {
PandaNode *node = data.node();
const RenderEffects *node_effects = node->get_effects();
if (node_effects->has_decal()) {
bool has_decal = node_effects->has_decal();
if (has_decal && !_depth_offset_decals) {
// Start the three-pass decal rendering if we're not using
// DepthOffsetAttribs to implement decals.
start_decal(data);
} else {
@ -150,7 +152,21 @@ traverse_below(const CullTraverserData &data) {
_cull_handler->record_object(object);
}
}
if (has_decal) {
// If we *are* implementing decals with DepthOffsetAttribs,
// apply it now, so that each child of this node gets offset by
// a tiny amount.
data._state = data._state->compose(get_depth_offset_state());
#ifndef NDEBUG
// This is just a sanity check message.
if (!node->is_geom_node()) {
pgraph_cat.error()
<< "DecalEffect applied to " << *node << ", not a GeomNode.\n";
}
#endif
}
// Now visit all the node's children. We cannot use the
// node->get_children() interface, because that will keep a read
// pointer open, and we might end up changing this node during the
@ -246,6 +262,7 @@ get_bounds_outer_viz_state() {
(ColorAttrib::make_flat(Colorf(0.3f, 1.0f, 0.5f, 1.0f)),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise));
state->ref(); // once more to guard against static destruction
}
return state;
}
@ -266,6 +283,26 @@ get_bounds_inner_viz_state() {
(ColorAttrib::make_flat(Colorf(0.15f, 0.5f, 0.25f, 1.0f)),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
CullFaceAttrib::make(CullFaceAttrib::M_cull_counter_clockwise));
state->ref(); // once more to guard against static destruction
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::get_depth_offset_state
// Access: Private, Static
// Description: Returns a RenderState for increasing the DepthOffset
// by one.
////////////////////////////////////////////////////////////////////
CPT(RenderState) qpCullTraverser::
get_depth_offset_state() {
// Once someone asks for this pointer, we hold its reference count
// and never free it.
static CPT(RenderState) state = (const RenderState *)NULL;
if (state == (const RenderState *)NULL) {
state = RenderState::make
(DepthOffsetAttrib::make(1));
state->ref(); // once more to guard against static destruction
}
return state;
}

View File

@ -22,6 +22,7 @@
#include "pandabase.h"
#include "geom.h"
#include "sceneSetup.h"
#include "renderState.h"
#include "transformState.h"
#include "geometricBoundingVolume.h"
@ -48,17 +49,20 @@ public:
qpCullTraverser();
qpCullTraverser(const qpCullTraverser &copy);
INLINE void set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
INLINE void set_camera_mask(const DrawMask &camera_mask);
INLINE const DrawMask &get_camera_mask() const;
INLINE const TransformState *get_camera_transform() const;
INLINE const TransformState *get_render_transform() const;
INLINE void set_initial_state(const RenderState *initial_state);
INLINE const RenderState *get_initial_state() const;
INLINE void set_camera_mask(const DrawMask &draw_mask);
INLINE const DrawMask &get_camera_mask() const;
INLINE void set_camera_transform(const TransformState *camera_transform);
INLINE const TransformState *get_camera_transform() const;
INLINE void set_render_transform(const TransformState *render_transform);
INLINE const TransformState *get_render_transform() const;
INLINE void set_depth_offset_decals(bool flag);
INLINE bool get_depth_offset_decals() const;
INLINE void set_view_frustum(GeometricBoundingVolume *view_frustum);
INLINE GeometricBoundingVolume *get_view_frustum() const;
@ -69,24 +73,24 @@ public:
INLINE void set_cull_handler(CullHandler *cull_handler);
INLINE CullHandler *get_cull_handler() const;
void traverse(qpNodePath &root);
void traverse(const qpNodePath &root);
void traverse(CullTraverserData &data);
void traverse_below(const CullTraverserData &data);
void traverse_below(CullTraverserData &data);
private:
void show_bounds(CullTraverserData &data);
PT(Geom) make_bounds_viz(const BoundingVolume &vol);
CPT(RenderState) get_bounds_outer_viz_state();
CPT(RenderState) get_bounds_inner_viz_state();
CPT(RenderState) get_depth_offset_state();
void start_decal(const CullTraverserData &data);
CullableObject *r_get_decals(CullTraverserData &data,
CullableObject *decals);
CPT(RenderState) _initial_state;
PT(SceneSetup) _scene_setup;
DrawMask _camera_mask;
CPT(TransformState) _camera_transform;
CPT(TransformState) _render_transform;
CPT(RenderState) _initial_state;
bool _depth_offset_decals;
PT(GeometricBoundingVolume) _view_frustum;
PT(GeometricBoundingVolume) _guard_band;
CullHandler *_cull_handler;

View File

@ -17,29 +17,6 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpLensNode::
qpLensNode(const string &name) :
PandaNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpLensNode::
qpLensNode(const qpLensNode &copy) :
PandaNode(copy),
_lens(copy._lens)
{
}
////////////////////////////////////////////////////////////////////
// Function: copy_lens
// Access: Public
@ -73,6 +50,6 @@ set_lens(Lens *lens) {
// not yet a Lens associated.
////////////////////////////////////////////////////////////////////
INLINE Lens *qpLensNode::
get_lens() {
get_lens() const {
return _lens;
}

View File

@ -21,6 +21,42 @@
TypeHandle qpLensNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpLensNode::
qpLensNode(const string &name) :
PandaNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
qpLensNode::
qpLensNode(const qpLensNode &copy) :
PandaNode(copy),
_lens(copy._lens)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::xform
// Access: Public, Virtual
// Description: Transforms the contents of this PandaNode by the
// indicated matrix, if it means anything to do so. For
// most kinds of PandaNodes, this does nothing.
////////////////////////////////////////////////////////////////////
void qpLensNode::
xform(const LMatrix4f &mat) {
PandaNode::xform(mat);
// We need to actually transform the lens here.
}
////////////////////////////////////////////////////////////////////
// Function: qpLensNode::make_copy
// Access: Public, Virtual

View File

@ -34,20 +34,21 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpLensNode : public PandaNode {
PUBLISHED:
INLINE qpLensNode(const string &name);
qpLensNode(const string &name);
protected:
INLINE qpLensNode(const qpLensNode &copy);
qpLensNode(const qpLensNode &copy);
public:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
virtual void xform(const LMatrix4f &mat);
virtual PandaNode *make_copy() const;
PUBLISHED:
INLINE void copy_lens(const Lens &lens);
INLINE void set_lens(Lens *lens);
INLINE Lens *get_lens();
INLINE Lens *get_lens() const;
bool is_in_view(const LPoint3f &pos);

View File

@ -119,6 +119,7 @@ RenderState::
// as to the computed result (if any), so neither object will be
// tempted to destruct. Go ahead and remove ourselves from the
// other cache.
nassertv(other->_composition_cache.count(this) == 1);
other->_composition_cache.erase(this);
// It's all right if the other state destructs now, since it

View File

@ -0,0 +1,145 @@
// Filename: sceneSetup.I
// Created by: drose (27Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE SceneSetup::
SceneSetup() {
_camera_transform = TransformState::make_identity();
_render_transform = TransformState::make_identity();
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::set_scene_root
// Access: Public
// Description: Specifies the root node of the scene.
////////////////////////////////////////////////////////////////////
INLINE void SceneSetup::
set_scene_root(const qpNodePath &scene_root) {
_scene_root = scene_root;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::get_scene_root
// Access: Public
// Description: Returns the root node of the scene.
////////////////////////////////////////////////////////////////////
INLINE const qpNodePath &SceneSetup::
get_scene_root() const {
return _scene_root;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::set_camera
// Access: Public
// Description: Specifies the camera used to render the scene.
////////////////////////////////////////////////////////////////////
INLINE void SceneSetup::
set_camera(const qpCamera *camera) {
_camera = camera;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::get_camera
// Access: Public
// Description: Returns the camera used to render the scene.
////////////////////////////////////////////////////////////////////
INLINE const qpCamera *SceneSetup::
get_camera() const {
return _camera;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::set_lens
// Access: Public
// Description: Indicates the particular Lens used for rendering.
////////////////////////////////////////////////////////////////////
INLINE void SceneSetup::
set_lens(const Lens *lens) {
_lens = lens;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::get_lens
// Access: Public
// Description: Returns the particular Lens used for rendering.
////////////////////////////////////////////////////////////////////
INLINE const Lens *SceneSetup::
get_lens() const {
return _lens;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::set_camera_transform
// Access: Public
// Description: Specifies the position of the camera relative to the
// starting node, without any compensating
// coordinate-system transforms that might have been
// introduced for the purposes of rendering.
////////////////////////////////////////////////////////////////////
INLINE void SceneSetup::
set_camera_transform(const TransformState *camera_transform) {
_camera_transform = camera_transform;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::get_camera_transform
// Access: Public
// Description: Returns the position of the camera relative to the
// starting node, without any compensating
// coordinate-system transforms that might have been
// introduced for the purposes of rendering.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *SceneSetup::
get_camera_transform() const {
return _camera_transform;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::set_render_transform
// Access: Public
// Description: Specifies the position of the starting node relative
// to the camera, pretransformed as appropriate for
// rendering.
////////////////////////////////////////////////////////////////////
INLINE void SceneSetup::
set_render_transform(const TransformState *render_transform) {
_render_transform = render_transform;
}
////////////////////////////////////////////////////////////////////
// Function: SceneSetup::get_render_transform
// Access: Public
// Description: Returns the position of the starting node relative
// to the camera, pretransformed as appropriate for
// rendering.
//
// Note that this value is always the position of the
// starting node, not the current node, even if it is
// sampled during a traversal. To get the render
// transform of the current node check in the current
// CullTraverserData.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *SceneSetup::
get_render_transform() const {
return _render_transform;
}

View File

@ -0,0 +1,20 @@
// Filename: sceneSetup.cxx
// Created by: drose (27Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "sceneSetup.h"

View File

@ -0,0 +1,66 @@
// Filename: sceneSetup.h
// Created by: drose (27Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef SCENESETUP_H
#define SCENESETUP_H
#include "pandabase.h"
#include "referenceCount.h"
#include "qpnodePath.h"
#include "qpcamera.h"
#include "transformState.h"
#include "lens.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : SceneSetup
// Description : This object holds the camera position, etc., and
// other general setup information for rendering a
// particular scene.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA SceneSetup : public ReferenceCount {
public:
INLINE SceneSetup();
INLINE void set_scene_root(const qpNodePath &scene_root);
INLINE const qpNodePath &get_scene_root() const;
INLINE void set_camera(const qpCamera *camera);
INLINE const qpCamera *get_camera() const;
INLINE void set_lens(const Lens *lens);
INLINE const Lens *get_lens() const;
INLINE void set_camera_transform(const TransformState *camera_transform);
INLINE const TransformState *get_camera_transform() const;
INLINE void set_render_transform(const TransformState *render_transform);
INLINE const TransformState *get_render_transform() const;
private:
qpNodePath _scene_root;
CPT(qpCamera) _camera;
CPT(Lens) _lens;
CPT(TransformState) _camera_transform;
CPT(TransformState) _render_transform;
};
#include "sceneSetup.I"
#endif

View File

@ -482,9 +482,6 @@ event_L(CPT_Event) {
}
void demo_keys(EventHandler&) {
new RenderRelation( lights, dlight );
have_dlight = true;
/*
event_handler.add_hook("mw-in-label2d", event_in_label2d);
event_handler.add_hook("mw-out-label2d", event_out_label2d);

View File

@ -49,6 +49,9 @@
#include "eventQueue.h"
#include "eventHandler.h"
#include "qpdataGraphTraverser.h"
#include "lightAttrib.h"
#include "ambientLight.h"
#include "directionalLight.h"
// Use dconfig to read a few Configrc variables.
Configure(config_pview);
@ -64,6 +67,7 @@ bool run_flag = true;
// These are referenced in both event_w() and in event_b().
bool wireframe = false;
bool two_sided = false;
bool lighting = false;
// These are used by report_frame_rate().
@ -76,6 +80,9 @@ static const int override_priority = 100;
// This is the main scene graph.
qpNodePath render;
// And this is the camera node.
qpNodePath camera_np;
void
report_frame_rate() {
double now = ClockObject::get_global_clock()->get_frame_time();
@ -361,6 +368,37 @@ event_A(CPT_Event) {
#endif
}
void
event_l(CPT_Event) {
// 'l' : toggle lighting.
lighting = !lighting;
if (lighting) {
nout << "Enabling lighting.\n";
static bool lights_created = false;
static PT(AmbientLight) alight;
static PT(DirectionalLight) dlight;
if (!lights_created) {
alight = new AmbientLight("ambient");
alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
dlight = new DirectionalLight("directional");
camera_np.attach_new_node(alight);
camera_np.attach_new_node(dlight);
lights_created = true;
}
// Enable lights on the top node.
render.node()->set_attrib(LightAttrib::make(LightAttrib::O_add, alight, dlight));
} else {
nout << "Disabling lighting.\n";
// Remove the lights from the top node.
render.node()->clear_attrib(LightAttrib::get_class_type());
}
}
int
main(int argc, char *argv[]) {
// First, we need a GraphicsPipe, before we can open a window.
@ -375,7 +413,7 @@ main(int argc, char *argv[]) {
// Now we just need to make a scene graph for the camera to render.
render = qpNodePath("render");
render.attach_new_node(camera);
camera_np = render.attach_new_node(camera);
camera->set_scene(render);
// This is maybe here temporarily, and maybe not.
@ -398,6 +436,7 @@ main(int argc, char *argv[]) {
event_handler.add_hook("s", event_s);
event_handler.add_hook("shift-s", event_S);
event_handler.add_hook("shift-a", event_A);
event_handler.add_hook("l", event_l);
// Put something in the scene graph to look at.