pgraph lighting, optional offset decal implementation
This commit is contained in:
parent
333bfc3050
commit
783ba052d7
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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 ©) :
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
||||
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 ¶ms);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
||||
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 ©);
|
||||
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 ¶ms);
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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 ©) :
|
||||
_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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
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 ©);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 ¶ms);
|
||||
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
|
||||
|
||||
|
|
@ -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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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 ©) :
|
||||
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);
|
||||
}
|
||||
|
|
@ -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 ©);
|
||||
|
||||
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
|
||||
|
|
@ -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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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 ©) :
|
||||
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);
|
||||
}
|
||||
|
|
@ -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 ©);
|
||||
|
||||
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
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "config_light.cxx"
|
||||
#include "ambientLight.cxx"
|
||||
#include "spotlight.cxx"
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
||||
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 ©);
|
||||
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 ¶ms);
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
||||
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 ©);
|
||||
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 ¶ms);
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -29,11 +29,9 @@
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullHandler::
|
||||
~CullHandler()
|
||||
{
|
||||
~CullHandler() {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullHandler::record_object
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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 ©) :
|
|||
// 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
qpLensNode(const qpLensNode ©);
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue