mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
pgraph billboards
This commit is contained in:
parent
e274be72af
commit
4fac7d8fbf
@ -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);
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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 \
|
||||
|
153
panda/src/pgraph/billboardAttrib.I
Normal file
153
panda/src/pgraph/billboardAttrib.I
Normal 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;
|
||||
}
|
255
panda/src/pgraph/billboardAttrib.cxx
Normal file
255
panda/src/pgraph/billboardAttrib.cxx
Normal 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 ¶ms) {
|
||||
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);
|
||||
}
|
105
panda/src/pgraph/billboardAttrib.h
Normal file
105
panda/src/pgraph/billboardAttrib.h
Normal 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 ¶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, "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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -31,8 +31,7 @@ TypeHandle qpCamera::_type_handle;
|
||||
qpCamera::
|
||||
qpCamera(const string &name) :
|
||||
qpLensNode(name),
|
||||
_active(true),
|
||||
_scene((PandaNode *)NULL)
|
||||
_active(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user