pgraph billboards

This commit is contained in:
David Rose 2002-02-27 18:02:32 +00:00
parent e274be72af
commit 4fac7d8fbf
17 changed files with 664 additions and 44 deletions

View File

@ -137,8 +137,8 @@ cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) {
return;
}
PandaNode *scene = camera_node->get_scene();
if (scene == (PandaNode *)NULL) {
NodeChain scene = camera_node->get_scene();
if (scene.is_empty()) {
// No scene, no draw.
return;
}
@ -161,20 +161,22 @@ cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) {
// The world transform is computed from the camera's position; we
// then might need to adjust it into the GSG's internal coordinate
// system.
CPT(TransformState) world_transform = camera.get_rel_transform(NodeChain());
trav.set_camera_transform(scene.get_rel_transform(camera));
CPT(TransformState) render_transform = camera.get_rel_transform(scene);
CoordinateSystem external_cs = gsg->get_coordinate_system();
CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
if (internal_cs != CS_default && internal_cs != external_cs) {
CPT(TransformState) cs_transform =
TransformState::make_mat(LMatrix4f::convert_mat(external_cs, internal_cs));
world_transform = cs_transform->compose(world_transform);
render_transform = cs_transform->compose(render_transform);
}
trav.set_world_transform(world_transform);
trav.set_render_transform(render_transform);
DisplayRegionStack old_dr = gsg->push_display_region(dr);
gsg->prepare_display_region();
trav.traverse(scene);
trav.traverse(scene.node());
gsg->pop_display_region(old_dr);
}

View File

@ -24,6 +24,7 @@
#include "transformState.h"
#include "textureAttrib.h"
#include "texturePool.h"
#include "billboardAttrib.h"
#include "qpgeomNode.h"
#include "string_utils.h"
#include "eggPrimitive.h"
@ -985,13 +986,13 @@ setup_bucket(BuilderBucket &bucket, PandaNode *parent,
bin = render_mode->get_bin();
}
bucket._state = bucket._state->add(TextureAttrib::make_off());
bucket._state = bucket._state->add_attrib(TextureAttrib::make_off());
if (egg_prim->has_texture()) {
PT(EggTexture) egg_tex = egg_prim->get_texture();
const TextureDef &def = _textures[egg_tex];
if (def._texture != (const RenderAttrib *)NULL) {
bucket._state = bucket._state->add(def._texture);
bucket._state = bucket._state->add_attrib(def._texture);
// bucket._trans.set_transition(def._apply);
// If neither the primitive nor the texture specified an alpha
@ -1499,25 +1500,23 @@ create_group_arc(EggGroup *egg_group, PandaNode *parent, PandaNode *node) {
node->set_transform(TransformState::make_mat(matf));
}
/*
// If the group has a billboard flag, apply that.
switch (egg_group->get_billboard_type()) {
case EggGroup::BT_point_camera_relative:
arc->set_transition(new BillboardTransition(BillboardTransition::point_eye()));
node->set_attrib(BillboardAttrib::make_point_eye());
break;
case EggGroup::BT_point_world_relative:
arc->set_transition(new BillboardTransition(BillboardTransition::point_world()));
node->set_attrib(BillboardAttrib::make_point_world());
break;
case EggGroup::BT_axis:
arc->set_transition(new BillboardTransition(BillboardTransition::axis()));
node->set_attrib(BillboardAttrib::make_axis());
break;
case EggGroup::BT_none:
break;
}
*/
/*
if (egg_group->get_decal_flag()) {

View File

@ -6,6 +6,7 @@
#define TARGET pgraph
#define SOURCES \
billboardAttrib.h billboardAttrib.I \
qpcamera.h qpcamera.I \
colorAttrib.h colorAttrib.I \
config_pgraph.h \
@ -29,6 +30,7 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define INCLUDED_SOURCES \
billboardAttrib.cxx \
qpcamera.cxx \
colorAttrib.cxx \
config_pgraph.cxx \
@ -57,6 +59,7 @@
#endif
#define INSTALL_HEADERS \
billboardAttrib.h billboardAttrib.I \
qpcamera.h qpcamera.I \
colorAttrib.h colorAttrib.I \
config_pgraph.h \

View File

@ -0,0 +1,153 @@
// Filename: billboardAttrib.I
// Created by: drose (27Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: BillboardAttrib::Constructor
// Access: Private
// Description: Use BillboardAttrib::make() to construct a new
// BillboardAttrib object.
////////////////////////////////////////////////////////////////////
INLINE BillboardAttrib::
BillboardAttrib() {
_off = true;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_axis
// Access: Published, Static
// Description: A convenience function to make a typical
// axis-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
make_axis() {
return make(LVector3f::up(), false, true,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_point_eye
// Access: Published, Static
// Description: A convenience function to make a typical
// eye-relative point-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
make_point_eye() {
return make(LVector3f::up(), true, false,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_point_world
// Access: Published, Static
// Description: A convenience function to make a typical
// world-relative point-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
make_point_world() {
return make(LVector3f::up(), false, false,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::is_off
// Access: Published
// Description: Returns true if the BillboardAttrib is an 'off'
// BillboardAttrib, indicating that it does not enable
// billboarding. This kind of BillboardAttrib isn't
// particularly useful and isn't normally created or
// stored in the graph; it might be implicitly
// discovered as the result of a
// NodeChain::get_rel_state().
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
is_off() const {
return _off;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_up_vector
// Access: Published
// Description: Returns the up vector in effect for this billboard.
////////////////////////////////////////////////////////////////////
INLINE const LVector3f &BillboardAttrib::
get_up_vector() const {
return _up_vector;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_eye_relative
// Access: Published
// Description: Returns true if this billboard interprets the up
// vector relative to the camera, or false if it is
// relative to the world.
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
get_eye_relative() const {
return _eye_relative;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_axial_rotate
// Access: Published
// Description: Returns true if this billboard rotates only around
// the axis of the up vector, or false if it rotates
// freely in three dimensions.
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
get_axial_rotate() const {
return _axial_rotate;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_offset
// Access: Published
// Description: Returns the distance toward the camera (or the
// look_at_point) the billboard is moved towards, after
// rotating. This can be used to ensure the billboard
// is not obscured by nearby geometry.
////////////////////////////////////////////////////////////////////
INLINE float BillboardAttrib::
get_offset() const {
return _offset;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_look_at
// Access: Published
// Description: Returns the node this billboard will rotate to look
// towards. If this is empty, it means the billboard
// will rotate towards the current camera node, wherever
// that might be.
////////////////////////////////////////////////////////////////////
INLINE const NodeChain &BillboardAttrib::
get_look_at() const {
return _look_at;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_look_at_point
// Access: Published
// Description: Returns the point, relative to the look_at node,
// towards which the billboard will rotate. Normally
// this is (0, 0, 0).
////////////////////////////////////////////////////////////////////
INLINE const LPoint3f &BillboardAttrib::
get_look_at_point() const {
return _look_at_point;
}

View File

@ -0,0 +1,255 @@
// Filename: billboardAttrib.cxx
// Created by: drose (27Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "billboardAttrib.h"
#include "look_at.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle BillboardAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make
// Access: Published, Static
// Description: Constructs a new BillboardAttrib object with the
// indicated properties.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) BillboardAttrib::
make(const LVector3f &up_vector, bool eye_relative,
bool axial_rotate, float offset, const NodeChain &look_at,
const LPoint3f &look_at_point) {
BillboardAttrib *attrib = new BillboardAttrib;
attrib->_up_vector = up_vector;
attrib->_eye_relative = eye_relative;
attrib->_axial_rotate = axial_rotate;
attrib->_offset = offset;
attrib->_look_at = look_at;
attrib->_look_at_point = look_at_point;
attrib->_off = false;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
output(ostream &out) const {
out << get_type() << ":";
if (is_off()) {
out << "(off)";
} else {
if (_axial_rotate) {
out << "(axis";
} else {
out << "(point";
}
if (!_up_vector.almost_equal(LVector3f::up())) {
out << " up " << _up_vector;
}
if (_eye_relative) {
out << " eye";
}
if (_offset != 0.0f) {
out << " offset " << _offset;
}
if (!_look_at.is_empty()) {
out << " look at " << _look_at;
}
if (!_look_at_point.almost_equal(LPoint3f(0.0f, 0.0f, 0.0f))) {
out << " look at point " << _look_at_point;
}
out << ")";
}
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::do_billboard
// Access: Public
// Description: Computes the appropriate transform to apply to the
// billboarded geometry, given its current net
// transform, and the camera's inverse net transform.
////////////////////////////////////////////////////////////////////
CPT(TransformState) BillboardAttrib::
do_billboard(const TransformState *net_transform,
const TransformState *camera_transform) const {
// Determine the relative transform to our camera (or other look_at
// coordinate space).
CPT(TransformState) rel_transform =
net_transform->invert_compose(camera_transform);
const LMatrix4f &rel_mat = rel_transform->get_mat();
// Determine the look_at point in the camera space.
LVector3f camera_pos, up;
// If this is an eye-relative Billboard, then (a) the up vector is
// relative to the camera, not to the world, and (b) the look
// direction is towards the plane that contains the camera,
// perpendicular to the forward direction, not directly to the
// camera.
if (_eye_relative) {
up = _up_vector * rel_mat;
camera_pos = LVector3f::forward() * rel_mat;
} else {
// camera_pos= -rel_mat.get_row3(3);
camera_pos[0] = -rel_mat(3,0);
camera_pos[1] = -rel_mat(3,1);
camera_pos[2] = -rel_mat(3,2);
up = _up_vector;
}
// Now determine the rotation matrix for the Billboard.
LMatrix4f rotate;
if (_axial_rotate) {
heads_up(rotate, camera_pos, up);
} else {
look_at(rotate, camera_pos, up);
}
// Also slide the billboard geometry towards the camera according to
// the offset factor.
if (_offset != 0.0f) {
LVector3f translate(rel_mat(3, 0), rel_mat(3, 1), rel_mat(3, 2));
translate.normalize();
translate *= _offset;
rotate.set_row(3, translate);
}
return TransformState::make_mat(rotate);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived BillboardAttrib
// types to return a unique number indicating whether
// this BillboardAttrib is equivalent to the other one.
//
// This should return 0 if the two BillboardAttrib 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 BillboardAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int BillboardAttrib::
compare_to_impl(const RenderAttrib *other) const {
const BillboardAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (_axial_rotate != ta->_axial_rotate) {
return _axial_rotate - ta->_axial_rotate;
}
if (_eye_relative != ta->_eye_relative) {
return _eye_relative - ta->_eye_relative;
}
if (_offset != ta->_offset) {
return _offset < ta->_offset ? -1 : 1;
}
int compare = _up_vector.compare_to(ta->_up_vector);
if (compare != 0) {
return compare;
}
compare = _look_at.compare_to(ta->_look_at);
if (compare != 0) {
return compare;
}
compare = _look_at_point.compare_to(ta->_look_at_point);
if (compare != 0) {
return compare;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived BillboardAttrib
// types to specify what the default property for a
// BillboardAttrib of this type should be.
//
// This should return a newly-allocated BillboardAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of BillboardAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *BillboardAttrib::
make_default_impl() const {
return new BillboardAttrib;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// BillboardAttrib.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type BillboardAttrib is encountered
// in the Bam file. It should create the BillboardAttrib
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *BillboardAttrib::
make_from_bam(const FactoryParams &params) {
BillboardAttrib *attrib = new BillboardAttrib;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::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 BillboardAttrib.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
}

View File

@ -0,0 +1,105 @@
// Filename: billboardAttrib.h
// Created by: drose (27Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 BILLBOARDATTRIB_H
#define BILLBOARDATTRIB_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "luse.h"
#include "nodeChain.h"
////////////////////////////////////////////////////////////////////
// Class : BillboardAttrib
// Description : Indicates that geometry at this node should
// automatically rotate to face the camera, or any other
// arbitrary node.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA BillboardAttrib : public RenderAttrib {
private:
INLINE BillboardAttrib();
PUBLISHED:
static CPT(RenderAttrib) make(const LVector3f &up_vector,
bool eye_relative,
bool axial_rotate,
float offset,
const NodeChain &look_at,
const LPoint3f &look_at_point);
INLINE static CPT(RenderAttrib) make_axis();
INLINE static CPT(RenderAttrib) make_point_eye();
INLINE static CPT(RenderAttrib) make_point_world();
INLINE bool is_off() const;
INLINE const LVector3f &get_up_vector() const;
INLINE bool get_eye_relative() const;
INLINE bool get_axial_rotate() const;
INLINE float get_offset() const;
INLINE const NodeChain &get_look_at() const;
INLINE const LPoint3f &get_look_at_point() const;
public:
virtual void output(ostream &out) const;
CPT(TransformState) do_billboard(const TransformState *net_transform,
const TransformState *camera_transform) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
bool _off;
LVector3f _up_vector;
bool _eye_relative;
bool _axial_rotate;
float _offset;
NodeChain _look_at;
LPoint3f _look_at_point;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "BillboardAttrib",
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 "billboardAttrib.I"
#endif

View File

@ -18,6 +18,7 @@
#include "config_pgraph.h"
#include "billboardAttrib.h"
#include "qpcamera.h"
#include "colorAttrib.h"
#include "qpgeomNode.h"
@ -57,6 +58,7 @@ init_libpgraph() {
}
initialized = true;
BillboardAttrib::init_type();
qpCamera::init_type();
ColorAttrib::init_type();
qpGeomNode::init_type();
@ -70,6 +72,7 @@ init_libpgraph() {
ColorAttrib::init_type();
TransformState::init_type();
BillboardAttrib::register_with_read_factory();
ColorAttrib::register_with_read_factory();
qpGeomNode::register_with_read_factory();
PandaNode::register_with_read_factory();

View File

@ -249,7 +249,7 @@ get_child_sort(int n) const {
INLINE void PandaNode::
set_attrib(const RenderAttrib *attrib, int override) {
CDWriter cdata(_cycler);
cdata->_state = cdata->_state->add(attrib, override);
cdata->_state = cdata->_state->add_attrib(attrib, override);
}
////////////////////////////////////////////////////////////////////
@ -282,7 +282,7 @@ get_attrib(TypeHandle type) const {
INLINE void PandaNode::
clear_attrib(TypeHandle type) {
CDWriter cdata(_cycler);
cdata->_state = cdata->_state->remove(type);
cdata->_state = cdata->_state->remove_attrib(type);
}
////////////////////////////////////////////////////////////////////

View File

@ -48,7 +48,7 @@ is_active() const {
// represent the root of any subgraph.
////////////////////////////////////////////////////////////////////
INLINE void qpCamera::
set_scene(PandaNode *scene) {
set_scene(const NodeChain &scene) {
_scene = scene;
}
@ -58,7 +58,7 @@ set_scene(PandaNode *scene) {
// Description: Returns the scene that will be rendered by the
// camera. See set_scene().
////////////////////////////////////////////////////////////////////
INLINE PandaNode *qpCamera::
INLINE const NodeChain &qpCamera::
get_scene() const {
return _scene;
}

View File

@ -31,8 +31,7 @@ TypeHandle qpCamera::_type_handle;
qpCamera::
qpCamera(const string &name) :
qpLensNode(name),
_active(true),
_scene((PandaNode *)NULL)
_active(true)
{
}

View File

@ -22,9 +22,9 @@
#include "pandabase.h"
#include "qplensNode.h"
#include "nodeChain.h"
class DisplayRegion;
class PandaNode;
////////////////////////////////////////////////////////////////////
// Class : qpCamera
@ -49,8 +49,8 @@ PUBLISHED:
INLINE void set_active(bool active);
INLINE bool is_active() const;
INLINE void set_scene(PandaNode *scene);
INLINE PandaNode *get_scene() const;
INLINE void set_scene(const NodeChain &scene);
INLINE const NodeChain &get_scene() const;
INLINE int get_num_display_regions() const;
INLINE DisplayRegion *get_display_region(int n) const;
@ -60,7 +60,7 @@ private:
void remove_display_region(DisplayRegion *display_region);
bool _active;
PandaNode *_scene;
NodeChain _scene;
typedef pvector<DisplayRegion *> DisplayRegions;
DisplayRegions _display_regions;

View File

@ -19,6 +19,7 @@
#include "qpcullTraverser.h"
#include "transformState.h"
#include "renderState.h"
#include "billboardAttrib.h"
#include "cullHandler.h"
#include "dcast.h"
#include "qpgeomNode.h"
@ -31,7 +32,8 @@
qpCullTraverser::
qpCullTraverser() {
_initial_state = RenderState::make_empty();
_world_transform = DCAST(TransformState, TransformState::make_identity());
_camera_transform = DCAST(TransformState, TransformState::make_identity());
_render_transform = DCAST(TransformState, TransformState::make_identity());
_cull_handler = (CullHandler *)NULL;
}
@ -48,14 +50,28 @@ set_initial_state(const RenderState *initial_state) {
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_world_transform
// Function: qpCullTraverser::set_camera_transform
// Access: Public
// Description: Specifies the position of the world relative to the
// camera.
// 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.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
set_world_transform(const TransformState *world_transform) {
_world_transform = world_transform;
set_camera_transform(const TransformState *camera_transform) {
_camera_transform = 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.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
set_render_transform(const TransformState *render_transform) {
_render_transform = render_transform;
}
////////////////////////////////////////////////////////////////////
@ -78,7 +94,8 @@ void qpCullTraverser::
traverse(PandaNode *root) {
nassertv(_cull_handler != (CullHandler *)NULL);
r_traverse(root, _world_transform, _initial_state, 0);
r_traverse(root, _render_transform, TransformState::make_identity(),
_initial_state, 0);
}
////////////////////////////////////////////////////////////////////
@ -87,11 +104,25 @@ traverse(PandaNode *root) {
// Description: The recursive traversal implementation.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
r_traverse(PandaNode *node, const TransformState *transform,
r_traverse(PandaNode *node,
const TransformState *render_transform,
const TransformState *net_transform,
const RenderState *state, int flags) {
CPT(TransformState) next_transform = transform->compose(node->get_transform());
CPT(TransformState) next_render_transform =
render_transform->compose(node->get_transform());
CPT(TransformState) next_net_transform =
net_transform->compose(node->get_transform());
CPT(RenderState) next_state = state->compose(node->get_state());
const BillboardAttrib *billboard = state->get_billboard();
if (billboard != (const BillboardAttrib *)NULL) {
// Got to apply a billboard transform here.
CPT(TransformState) billboard_transform =
billboard->do_billboard(net_transform, _camera_transform);
next_render_transform = next_render_transform->compose(billboard_transform);
next_net_transform = next_net_transform->compose(billboard_transform);
}
if (node->is_geom_node()) {
qpGeomNode *geom_node;
DCAST_INTO_V(geom_node, node);
@ -101,7 +132,7 @@ r_traverse(PandaNode *node, const TransformState *transform,
Geom *geom = geom_node->get_geom(i);
CPT(RenderState) geom_state =
next_state->compose(geom_node->get_geom_state(i));
_cull_handler->record_geom(geom, next_transform, geom_state);
_cull_handler->record_geom(geom, next_render_transform, geom_state);
}
}
@ -109,6 +140,6 @@ r_traverse(PandaNode *node, const TransformState *transform,
PandaNode::Children cr = node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
r_traverse(cr.get_child(i), next_transform, next_state, flags);
r_traverse(cr.get_child(i), next_render_transform, next_net_transform, next_state, flags);
}
}

View File

@ -41,17 +41,20 @@ public:
qpCullTraverser();
void set_initial_state(const RenderState *initial_state);
void set_world_transform(const TransformState *world_transform);
void set_camera_transform(const TransformState *camera_transform);
void set_render_transform(const TransformState *render_transform);
void set_cull_handler(CullHandler *cull_handler);
void traverse(PandaNode *root);
private:
void r_traverse(PandaNode *node, const TransformState *transform,
void r_traverse(PandaNode *node, const TransformState *render_transform,
const TransformState *net_transform,
const RenderState *state, int flags);
CPT(RenderState) _initial_state;
CPT(TransformState) _world_transform;
CPT(TransformState) _camera_transform;
CPT(TransformState) _render_transform;
CullHandler *_cull_handler;
};

View File

@ -148,3 +148,22 @@ get_override(int n) const {
nassertr(n >= 0 && n < (int)_attributes.size(), 0);
return _attributes[n]._override;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_billboard
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a BillboardAttrib on this state. It returns a
// pointer to the BillboardAttrib, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const BillboardAttrib *RenderState::
get_billboard() const {
if ((_flags & F_checked_billboard) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal billboard cache.
((RenderState *)this)->determine_billboard();
}
return _billboard;
}

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "renderState.h"
#include "billboardAttrib.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagramIterator.h"
@ -38,6 +39,7 @@ RenderState::
RenderState() {
_saved_entry = _states.end();
_self_compose = (RenderState *)NULL;
_flags = 0;
}
////////////////////////////////////////////////////////////////////
@ -399,7 +401,7 @@ invert_compose(const RenderState *other) const {
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::add
// Function: RenderState::add_attrib
// Access: Published
// Description: Returns a new RenderState object that represents the
// same as the source state, with the new RenderAttrib
@ -407,7 +409,7 @@ invert_compose(const RenderState *other) const {
// same type, it is replaced.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
add(const RenderAttrib *attrib, int override) const {
add_attrib(const RenderAttrib *attrib, int override) const {
RenderState *new_state = new RenderState;
back_insert_iterator<Attributes> result =
back_inserter(new_state->_attributes);
@ -441,14 +443,14 @@ add(const RenderAttrib *attrib, int override) const {
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::remove
// Function: RenderState::remove_attrib
// Access: Published
// Description: Returns a new RenderState object that represents the
// same as the source state, with the indicated
// RenderAttrib removed
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
remove(TypeHandle type) const {
remove_attrib(TypeHandle type) const {
RenderState *new_state = new RenderState;
back_insert_iterator<Attributes> result =
back_inserter(new_state->_attributes);
@ -466,6 +468,23 @@ remove(TypeHandle type) const {
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_attrib
// Access: Published, Virtual
// Description: Looks for a RenderAttrib of the indicated type in the
// state, and returns it if it is found, or NULL if it
// is not.
////////////////////////////////////////////////////////////////////
const RenderAttrib *RenderState::
get_attrib(TypeHandle type) const {
Attributes::const_iterator ai;
ai = _attributes.find(Attribute(type));
if (ai != _attributes.end()) {
return (*ai)._attrib;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::output
// Access: Published, Virtual
@ -807,6 +826,21 @@ do_invert_compose(const RenderState *other) const {
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_billboard
// Access: Private
// Description: This is the private implementation of
// get_billboard().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_billboard() {
const RenderAttrib *attrib = get_attrib(BillboardAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
_billboard = DCAST(BillboardAttrib, attrib);
}
_flags |= F_checked_billboard;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::register_with_read_factory
// Access: Public, Static

View File

@ -28,6 +28,7 @@
#include "ordered_vector.h"
class GraphicsStateGuardianBase;
class BillboardAttrib;
////////////////////////////////////////////////////////////////////
// Class : RenderState
@ -77,13 +78,17 @@ PUBLISHED:
CPT(RenderState) compose(const RenderState *other) const;
CPT(RenderState) invert_compose(const RenderState *other) const;
CPT(RenderState) add(const RenderAttrib *attrib, int override = 0) const;
CPT(RenderState) remove(TypeHandle type) const;
CPT(RenderState) add_attrib(const RenderAttrib *attrib, int override = 0) const;
CPT(RenderState) remove_attrib(TypeHandle type) const;
const RenderAttrib *get_attrib(TypeHandle type) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
public:
INLINE const BillboardAttrib *get_billboard() const;
CPT(RenderState) issue_delta_modify(const RenderState *other,
GraphicsStateGuardianBase *gsg) const;
CPT(RenderState) issue_delta_set(const RenderState *other,
@ -93,6 +98,7 @@ private:
static CPT(RenderState) return_new(RenderState *state);
CPT(RenderState) do_compose(const RenderState *other) const;
CPT(RenderState) do_invert_compose(const RenderState *other) const;
void determine_billboard();
private:
typedef pset<const RenderState *, IndirectLess<RenderState> > States;
@ -145,6 +151,14 @@ private:
typedef ov_set<Attribute> Attributes;
Attributes _attributes;
// We cache the pointer to the BillboardAttrib stored in the state,
// if there is one.
const BillboardAttrib *_billboard;
enum Flags {
F_checked_billboard = 0x0001,
};
short _flags;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);

View File

@ -270,7 +270,7 @@ main(int argc, char *argv[]) {
// Now we just need to make a scene graph for the camera to render.
PT(PandaNode) render = new PandaNode("render");
render->add_child(camera);
camera->set_scene(render);
camera->set_scene(NodeChain(render));
// Set up a data graph for tracking user input. For now, this uses
// the old-style graph interface.