mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
compute and load tangent and binormal
This commit is contained in:
parent
fa2e6eb726
commit
5d83609638
@ -17,3 +17,24 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::TBNVertexValue::operator <
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggGroupNode::TBNVertexValue::
|
||||
operator < (const TBNVertexValue &other) const {
|
||||
int compare = _pos.compare_to(other._pos);
|
||||
if (compare != 0) {
|
||||
return compare < 0;
|
||||
}
|
||||
compare = _normal.compare_to(other._normal);
|
||||
if (compare != 0) {
|
||||
return compare < 0;
|
||||
}
|
||||
compare = _uv.compare_to(other._uv);
|
||||
if (compare != 0) {
|
||||
return compare < 0;
|
||||
}
|
||||
return _uv_name < other._uv_name;
|
||||
}
|
||||
|
@ -695,6 +695,45 @@ strip_normals() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::recompute_tangent_binormal
|
||||
// Access: Published
|
||||
// Description: This function recomputes the tangent and binormal for
|
||||
// the named texture coordinate set for all vertices at
|
||||
// this level and below. Use the empty string for the
|
||||
// default texture coordinate set.
|
||||
//
|
||||
// It is necessary for each vertex to already have a
|
||||
// normal (or at least a polygon normal), as well as a
|
||||
// texture coordinate in the named texture coordinate
|
||||
// set, before calling this function. You might precede
|
||||
// this with recompute_vertex_normals() to ensure that
|
||||
// the normals exist.
|
||||
//
|
||||
// Like recompute_vertex_normals(), this function does
|
||||
// not remove or adjust vertices in the vertex pool; it
|
||||
// only adds new vertices with the normals removed.
|
||||
// Thus, it is a good idea to call
|
||||
// remove_unused_vertices() after calling this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggGroupNode::
|
||||
recompute_tangent_binormal(const GlobPattern &uv_name) {
|
||||
// First, collect all the vertices together with their shared
|
||||
// polygons.
|
||||
TBNVertexCollection collection;
|
||||
r_collect_tangent_binormal(uv_name, collection);
|
||||
|
||||
// Now compute the tangent and binormal separately for each common
|
||||
// group of vertices.
|
||||
TBNVertexCollection::const_iterator ci;
|
||||
for (ci = collection.begin(); ci != collection.end(); ++ci) {
|
||||
const TBNVertexValue &value = (*ci).first;
|
||||
const TBNVertexGroup &group = (*ci).second;
|
||||
|
||||
do_compute_tangent_binormal(value, group);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::triangulate_polygons
|
||||
// Access: Published
|
||||
@ -1644,7 +1683,7 @@ r_collect_vertex_normals(EggGroupNode::NVertexCollection &collection,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::r_collect_vertex_normals
|
||||
// Function: EggGroupNode::do_compute_vertex_normals
|
||||
// Access: Private
|
||||
// Description: This is part of the implementation of
|
||||
// recompute_vertex_normals(). It accepts a group of
|
||||
@ -1683,3 +1722,159 @@ do_compute_vertex_normals(const NVertexGroup &group) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::r_collect_tangent_binormal
|
||||
// Access: Private
|
||||
// Description: This is part of the implementation of
|
||||
// recompute_tangent_binormal(). It walks the scene
|
||||
// graph at this group node and below, identifying all
|
||||
// the polygons and the vertices they have in common.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggGroupNode::
|
||||
r_collect_tangent_binormal(const GlobPattern &uv_name,
|
||||
EggGroupNode::TBNVertexCollection &collection) {
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
EggNode *child = *ci;
|
||||
|
||||
if (child->is_of_type(EggPolygon::get_class_type())) {
|
||||
EggPolygon *polygon = DCAST(EggPolygon, child);
|
||||
|
||||
TBNVertexReference ref;
|
||||
ref._polygon = polygon;
|
||||
|
||||
// Now add each vertex from the polygon separately to our
|
||||
// collection.
|
||||
size_t num_vertices = polygon->size();
|
||||
for (size_t i = 0; i < num_vertices; i++) {
|
||||
// We look at the triangle formed by each three consecutive
|
||||
// vertices to determine the s direction and t direction at
|
||||
// each vertex. v1 is the key vertex, the one at position i;
|
||||
// v2 is vertex i + 1, and v3 is vertex i - 1.
|
||||
EggVertex *v1 = polygon->get_vertex(i);
|
||||
EggVertex *v2 = polygon->get_vertex((i + 1) % num_vertices);
|
||||
EggVertex *v3 = polygon->get_vertex((i + num_vertices - 1) % num_vertices);
|
||||
if (v1->has_normal() || polygon->has_normal()) {
|
||||
// Go through all of the UV names on the vertex, looking for
|
||||
// one that matches the glob pattern.
|
||||
EggVertex::const_uv_iterator uvi;
|
||||
for (uvi = v1->uv_begin(); uvi != v1->uv_end(); ++uvi) {
|
||||
EggVertexUV *uv_obj = (*uvi);
|
||||
string name = uv_obj->get_name();
|
||||
if (uv_name.matches(name) &&
|
||||
v2->has_uv(name) && v3->has_uv(name)) {
|
||||
TBNVertexValue value;
|
||||
value._uv_name = name;
|
||||
value._pos = v1->get_pos3();
|
||||
if (v1->has_normal()) {
|
||||
value._normal = v1->get_normal();
|
||||
} else {
|
||||
value._normal = polygon->get_normal();
|
||||
}
|
||||
value._uv = v1->get_uv(name);
|
||||
|
||||
// Compute the s direction and t direction for this vertex.
|
||||
LPoint3d p1 = v1->get_pos3();
|
||||
LPoint3d p2 = v2->get_pos3();
|
||||
LPoint3d p3 = v3->get_pos3();
|
||||
|
||||
TexCoordd w1 = v1->get_uv(name);
|
||||
TexCoordd w2 = v2->get_uv(name);
|
||||
TexCoordd w3 = v3->get_uv(name);
|
||||
|
||||
double x1 = p2[0] - p1[0];
|
||||
double x2 = p3[0] - p1[0];
|
||||
double y1 = p2[1] - p1[1];
|
||||
double y2 = p3[1] - p1[1];
|
||||
double z1 = p2[2] - p1[2];
|
||||
double z2 = p3[2] - p1[2];
|
||||
|
||||
double s1 = w2[0] - w1[0];
|
||||
double s2 = w3[0] - w1[0];
|
||||
double t1 = w2[1] - w1[1];
|
||||
double t2 = w3[1] - w1[1];
|
||||
|
||||
double r = 1.0f / (s1 * t2 - s2 * t1);
|
||||
ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
|
||||
(t2 * z1 - t1 * z2) * r);
|
||||
ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
|
||||
(s1 * z2 - s2 * z1) * r);
|
||||
|
||||
// Store the vertex referenced to the polygon.
|
||||
ref._vertex = i;
|
||||
collection[value].push_back(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
|
||||
EggGroupNode *group = DCAST(EggGroupNode, child);
|
||||
|
||||
// We can't share vertices across an Instance node. Don't
|
||||
// even bother trying. Instead, just restart.
|
||||
if (group->is_under_instance()) {
|
||||
group->recompute_tangent_binormal(uv_name);
|
||||
} else {
|
||||
group->r_collect_tangent_binormal(uv_name, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggGroupNode::do_compute_tangent_binormal
|
||||
// Access: Private
|
||||
// Description: This is part of the implementation of
|
||||
// recompute_tangent_binormal(). It accepts a group of
|
||||
// polygons and their common normals and UV's, and
|
||||
// computes the tangent and binormal for all their
|
||||
// shared vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggGroupNode::
|
||||
do_compute_tangent_binormal(const TBNVertexValue &value,
|
||||
const TBNVertexGroup &group) {
|
||||
nassertv(!group.empty());
|
||||
|
||||
// Accumulate together all of the s vectors and t vectors computed
|
||||
// for the different vertices that are together here.
|
||||
Normald sdir(0.0, 0.0, 0.0);
|
||||
Normald tdir(0.0, 0.0, 0.0);
|
||||
|
||||
TBNVertexGroup::const_iterator gi;
|
||||
for (gi = group.begin(); gi != group.end(); ++gi) {
|
||||
const TBNVertexReference &ref = (*gi);
|
||||
sdir += ref._sdir;
|
||||
tdir += ref._tdir;
|
||||
}
|
||||
|
||||
Normald tangent = (sdir - value._normal * value._normal.dot(sdir));
|
||||
tangent.normalize();
|
||||
|
||||
Normald binormal = cross(value._normal, tangent);
|
||||
if (dot(binormal, tdir) < 0.0f) {
|
||||
binormal = -binormal;
|
||||
}
|
||||
// Shouldn't need to normalize this, but we do just for good measure.
|
||||
binormal.normalize();
|
||||
|
||||
// Now we have the common tangent and binormal; apply them to all
|
||||
// the vertices.
|
||||
|
||||
for (gi = group.begin(); gi != group.end(); ++gi) {
|
||||
const TBNVertexReference &ref = (*gi);
|
||||
EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
|
||||
EggVertexPool *pool = vertex->get_pool();
|
||||
|
||||
EggVertex new_vertex(*vertex);
|
||||
EggVertexUV *uv_obj = new_vertex.get_uv_obj(value._uv_name);
|
||||
nassertv(uv_obj != (EggVertexUV *)NULL);
|
||||
uv_obj->set_tangent(tangent);
|
||||
uv_obj->set_binormal(binormal);
|
||||
|
||||
EggVertex *unique = pool->create_unique_vertex(new_vertex);
|
||||
unique->copy_grefs_from(*vertex);
|
||||
|
||||
ref._polygon->set_vertex(ref._vertex, unique);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "typedObject.h"
|
||||
#include "pointerTo.h"
|
||||
#include "luse.h"
|
||||
|
||||
#include "globPattern.h"
|
||||
#include "plist.h"
|
||||
|
||||
class EggTextureCollection;
|
||||
@ -130,6 +130,8 @@ PUBLISHED:
|
||||
void recompute_polygon_normals(CoordinateSystem cs = CS_default);
|
||||
void strip_normals();
|
||||
|
||||
void recompute_tangent_binormal(const GlobPattern &uv_name);
|
||||
|
||||
enum TriangulateFlags {
|
||||
T_polygon = 0x001,
|
||||
T_convex = 0x002,
|
||||
@ -197,6 +199,30 @@ private:
|
||||
double threshold, CoordinateSystem cs);
|
||||
void do_compute_vertex_normals(const NVertexGroup &group);
|
||||
|
||||
// This bit is in support of recompute_tangent_binormal().
|
||||
class TBNVertexReference {
|
||||
public:
|
||||
EggPolygon *_polygon;
|
||||
size_t _vertex;
|
||||
LVector3d _sdir;
|
||||
LVector3d _tdir;
|
||||
};
|
||||
class TBNVertexValue {
|
||||
public:
|
||||
INLINE bool operator < (const TBNVertexValue &other) const;
|
||||
Vertexd _pos;
|
||||
Normald _normal;
|
||||
string _uv_name;
|
||||
TexCoordd _uv;
|
||||
};
|
||||
typedef pvector<TBNVertexReference> TBNVertexGroup;
|
||||
typedef pmap<TBNVertexValue, TBNVertexGroup> TBNVertexCollection;
|
||||
|
||||
void r_collect_tangent_binormal(const GlobPattern &uv_name,
|
||||
TBNVertexCollection &collection);
|
||||
void do_compute_tangent_binormal(const TBNVertexValue &value,
|
||||
const TBNVertexGroup &group);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -412,6 +412,11 @@ transform(const LMatrix4d &mat) {
|
||||
morph.set_offset((*mi).get_offset() * mat);
|
||||
}
|
||||
|
||||
UVMap::iterator ui;
|
||||
for (ui = _uv_map.begin(); ui != _uv_map.end(); ++ui) {
|
||||
(*ui).second->transform(mat);
|
||||
}
|
||||
|
||||
EggAttributes::transform(mat);
|
||||
}
|
||||
|
||||
|
@ -295,26 +295,34 @@ has_uvs() const {
|
||||
// Function: EggVertexPool::get_uv_names
|
||||
// Access: Public
|
||||
// Description: Returns the list of UV names that are defined by any
|
||||
// vertices in the pool. It is the user's
|
||||
// responsibility to clear the vector before calling
|
||||
// this method.
|
||||
// vertices in the pool. Also returns the subset of UV
|
||||
// names that define the tangent and binormal. It is
|
||||
// the user's responsibility to clear both vectors
|
||||
// before calling this method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggVertexPool::
|
||||
get_uv_names(vector_string &uv_names) const {
|
||||
pset<string> names;
|
||||
get_uv_names(vector_string &uv_names, vector_string &tbn_names) const {
|
||||
pset<string> uv_names_set, tbn_names_set;
|
||||
IndexVertices::const_iterator ivi;
|
||||
for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
|
||||
EggVertex *vertex = (*ivi).second;
|
||||
EggVertex::const_uv_iterator uvi;
|
||||
for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
|
||||
names.insert((*uvi)->get_name());
|
||||
EggVertexUV *uv_obj = (*uvi);
|
||||
uv_names_set.insert(uv_obj->get_name());
|
||||
if (uv_obj->has_tangent() && uv_obj->has_binormal()) {
|
||||
tbn_names_set.insert(uv_obj->get_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pset<string>::const_iterator si;
|
||||
for (si = names.begin(); si != names.end(); ++si) {
|
||||
for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) {
|
||||
uv_names.push_back(*si);
|
||||
}
|
||||
for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) {
|
||||
tbn_names.push_back(*si);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -98,7 +98,7 @@ PUBLISHED:
|
||||
bool has_colors() const;
|
||||
bool has_nonwhite_colors() const;
|
||||
bool has_uvs() const;
|
||||
void get_uv_names(vector_string &uv_names) const;
|
||||
void get_uv_names(vector_string &uv_names, vector_string &tbn_names) const;
|
||||
|
||||
public:
|
||||
// Can be used to traverse all the vertices in index number order.
|
||||
|
@ -36,3 +36,87 @@ INLINE void EggVertexUV::
|
||||
set_uv(const TexCoordd &uv) {
|
||||
_uv = uv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::has_tangent
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool EggVertexUV::
|
||||
has_tangent() const {
|
||||
return (_flags & F_has_tangent) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::get_tangent
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Normald &EggVertexUV::
|
||||
get_tangent() const {
|
||||
nassertr(has_tangent(), _tangent);
|
||||
return _tangent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::set_tangent
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggVertexUV::
|
||||
set_tangent(const Normald &tangent) {
|
||||
_tangent = tangent;
|
||||
_flags |= F_has_tangent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::clear_tangent
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggVertexUV::
|
||||
clear_tangent() {
|
||||
_flags &= ~F_has_tangent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::has_binormal
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool EggVertexUV::
|
||||
has_binormal() const {
|
||||
return (_flags & F_has_binormal) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::get_binormal
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Normald &EggVertexUV::
|
||||
get_binormal() const {
|
||||
nassertr(has_binormal(), _binormal);
|
||||
return _binormal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::set_binormal
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggVertexUV::
|
||||
set_binormal(const Normald &binormal) {
|
||||
_binormal = binormal;
|
||||
_flags |= F_has_binormal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::clear_binormal
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggVertexUV::
|
||||
clear_binormal() {
|
||||
_flags &= ~F_has_binormal;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ TypeHandle EggVertexUV::_type_handle;
|
||||
EggVertexUV::
|
||||
EggVertexUV(const string &name, const TexCoordd &uv) :
|
||||
EggNamedObject(name),
|
||||
_flags(0),
|
||||
_uv(uv)
|
||||
{
|
||||
}
|
||||
@ -44,6 +45,9 @@ EggVertexUV::
|
||||
EggVertexUV(const EggVertexUV ©) :
|
||||
EggNamedObject(copy),
|
||||
_duvs(copy._duvs),
|
||||
_flags(copy._flags),
|
||||
_tangent(copy._tangent),
|
||||
_binormal(copy._binormal),
|
||||
_uv(copy._uv)
|
||||
{
|
||||
}
|
||||
@ -57,6 +61,9 @@ EggVertexUV &EggVertexUV::
|
||||
operator = (const EggVertexUV ©) {
|
||||
EggNamedObject::operator = (copy);
|
||||
_duvs = copy._duvs;
|
||||
_flags = copy._flags;
|
||||
_tangent = copy._tangent;
|
||||
_binormal = copy._binormal;
|
||||
_uv = copy._uv;
|
||||
|
||||
return (*this);
|
||||
@ -71,6 +78,25 @@ EggVertexUV::
|
||||
~EggVertexUV() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::transform
|
||||
// Access: Published, Virtual
|
||||
// Description: Applies the indicated transformation matrix to the
|
||||
// UV's tangent and/or binormal. This does nothing if
|
||||
// there is no tangent or binormal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggVertexUV::
|
||||
transform(const LMatrix4d &mat) {
|
||||
if (has_tangent()) {
|
||||
_tangent = _tangent * mat;
|
||||
_tangent.normalize();
|
||||
}
|
||||
if (has_binormal()) {
|
||||
_binormal = _binormal * mat;
|
||||
_binormal.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexUV::write
|
||||
// Access: Public
|
||||
@ -83,12 +109,20 @@ write(ostream &out, int indent_level) const {
|
||||
inline_name += ' ';
|
||||
}
|
||||
|
||||
if (_duvs.empty()) {
|
||||
if (_duvs.empty() && _flags == 0) {
|
||||
indent(out, indent_level)
|
||||
<< "<UV> " << inline_name << "{ " << get_uv() << " }\n";
|
||||
} else {
|
||||
indent(out, indent_level) << "<UV> " << inline_name << "{\n";
|
||||
indent(out, indent_level+2) << get_uv() << "\n";
|
||||
if (has_tangent()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "<Tangent> { " << get_tangent() << " }\n";
|
||||
}
|
||||
if (has_binormal()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "<Binormal> { " << get_binormal() << " }\n";
|
||||
}
|
||||
_duvs.write(out, indent_level+2);
|
||||
indent(out, indent_level) << "}\n";
|
||||
}
|
||||
@ -103,11 +137,29 @@ write(ostream &out, int indent_level) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggVertexUV::
|
||||
compare_to(const EggVertexUV &other) const {
|
||||
int compare =
|
||||
_uv.compare_to(other._uv, egg_parameters->_uv_threshold);
|
||||
if (_flags != other._flags) {
|
||||
return _flags - other._flags;
|
||||
}
|
||||
int compare;
|
||||
compare = _uv.compare_to(other._uv, egg_parameters->_uv_threshold);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
|
||||
if (has_tangent()) {
|
||||
compare = _tangent.compare_to(other._tangent, egg_parameters->_normal_threshold);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_binormal()) {
|
||||
compare = _binormal.compare_to(other._binormal, egg_parameters->_normal_threshold);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
|
||||
if (_duvs != other._duvs) {
|
||||
return _duvs < other._duvs ? -1 : 1;
|
||||
}
|
||||
|
@ -43,12 +43,32 @@ PUBLISHED:
|
||||
INLINE const TexCoordd &get_uv() const;
|
||||
INLINE void set_uv(const TexCoordd &texCoord);
|
||||
|
||||
INLINE bool has_tangent() const;
|
||||
INLINE const Normald &get_tangent() const;
|
||||
INLINE void set_tangent(const Normald &tangent);
|
||||
INLINE void clear_tangent();
|
||||
|
||||
INLINE bool has_binormal() const;
|
||||
INLINE const Normald &get_binormal() const;
|
||||
INLINE void set_binormal(const Normald &binormal);
|
||||
INLINE void clear_binormal();
|
||||
|
||||
void transform(const LMatrix4d &mat);
|
||||
|
||||
void write(ostream &out, int indent_level) const;
|
||||
int compare_to(const EggVertexUV &other) const;
|
||||
|
||||
EggMorphTexCoordList _duvs;
|
||||
|
||||
private:
|
||||
enum Flags {
|
||||
F_has_tangent = 0x001,
|
||||
F_has_binormal = 0x002,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
Normald _tangent;
|
||||
Normald _binormal;
|
||||
TexCoordd _uv;
|
||||
|
||||
public:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -351,6 +351,10 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
||||
accept();
|
||||
return BILLBOARDCENTER;
|
||||
}
|
||||
"<BINORMAL>" {
|
||||
accept();
|
||||
return BINORMAL;
|
||||
}
|
||||
"<BUNDLE>" {
|
||||
accept();
|
||||
return BUNDLE;
|
||||
@ -579,6 +583,10 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
||||
accept();
|
||||
return TAG;
|
||||
}
|
||||
"<TANGENT>" {
|
||||
accept();
|
||||
return TANGENT;
|
||||
}
|
||||
"<TEXLIST>" {
|
||||
accept();
|
||||
return TEXLIST;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,85 +8,87 @@
|
||||
# define BFACE 261
|
||||
# define BILLBOARD 262
|
||||
# define BILLBOARDCENTER 263
|
||||
# define BUNDLE 264
|
||||
# define CLOSED 265
|
||||
# define COLLIDE 266
|
||||
# define COMMENT 267
|
||||
# define COMPONENT 268
|
||||
# define COORDSYSTEM 269
|
||||
# define CV 270
|
||||
# define DART 271
|
||||
# define DNORMAL 272
|
||||
# define DRGBA 273
|
||||
# define DUV 274
|
||||
# define DXYZ 275
|
||||
# define DCS 276
|
||||
# define DISTANCE 277
|
||||
# define DTREF 278
|
||||
# define DYNAMICVERTEXPOOL 279
|
||||
# define EXTERNAL_FILE 280
|
||||
# define FLIGHT 281
|
||||
# define GROUP 282
|
||||
# define HIP 283
|
||||
# define INTANGENT 284
|
||||
# define JOINT 285
|
||||
# define KNOTS 286
|
||||
# define INCLUDE 287
|
||||
# define INSTANCE 288
|
||||
# define LINE 289
|
||||
# define LOOP 290
|
||||
# define MATERIAL 291
|
||||
# define MATRIX3 292
|
||||
# define MATRIX4 293
|
||||
# define MODEL 294
|
||||
# define MREF 295
|
||||
# define NORMAL 296
|
||||
# define NURBSCURVE 297
|
||||
# define NURBSSURFACE 298
|
||||
# define OBJECTTYPE 299
|
||||
# define ORDER 300
|
||||
# define OUTTANGENT 301
|
||||
# define POINTLIGHT 302
|
||||
# define POLYGON 303
|
||||
# define REF 304
|
||||
# define RGBA 305
|
||||
# define ROTATE 306
|
||||
# define ROTX 307
|
||||
# define ROTY 308
|
||||
# define ROTZ 309
|
||||
# define SANIM 310
|
||||
# define SCALAR 311
|
||||
# define SCALE 312
|
||||
# define SEQUENCE 313
|
||||
# define SHADING 314
|
||||
# define SWITCH 315
|
||||
# define SWITCHCONDITION 316
|
||||
# define TABLE 317
|
||||
# define TABLE_V 318
|
||||
# define TAG 319
|
||||
# define TEXLIST 320
|
||||
# define TEXTURE 321
|
||||
# define TLENGTHS 322
|
||||
# define TRANSFORM 323
|
||||
# define TRANSLATE 324
|
||||
# define TREF 325
|
||||
# define TRIANGLEFAN 326
|
||||
# define TRIANGLESTRIP 327
|
||||
# define TRIM 328
|
||||
# define TXT 329
|
||||
# define UKNOTS 330
|
||||
# define UV 331
|
||||
# define VKNOTS 332
|
||||
# define VERTEX 333
|
||||
# define VERTEXANIM 334
|
||||
# define VERTEXPOOL 335
|
||||
# define VERTEXREF 336
|
||||
# define XFMANIM 337
|
||||
# define XFMSANIM 338
|
||||
# define START_EGG 339
|
||||
# define START_GROUP_BODY 340
|
||||
# define START_TEXTURE_BODY 341
|
||||
# define START_PRIMITIVE_BODY 342
|
||||
# define BINORMAL 264
|
||||
# define BUNDLE 265
|
||||
# define CLOSED 266
|
||||
# define COLLIDE 267
|
||||
# define COMMENT 268
|
||||
# define COMPONENT 269
|
||||
# define COORDSYSTEM 270
|
||||
# define CV 271
|
||||
# define DART 272
|
||||
# define DNORMAL 273
|
||||
# define DRGBA 274
|
||||
# define DUV 275
|
||||
# define DXYZ 276
|
||||
# define DCS 277
|
||||
# define DISTANCE 278
|
||||
# define DTREF 279
|
||||
# define DYNAMICVERTEXPOOL 280
|
||||
# define EXTERNAL_FILE 281
|
||||
# define FLIGHT 282
|
||||
# define GROUP 283
|
||||
# define HIP 284
|
||||
# define INTANGENT 285
|
||||
# define JOINT 286
|
||||
# define KNOTS 287
|
||||
# define INCLUDE 288
|
||||
# define INSTANCE 289
|
||||
# define LINE 290
|
||||
# define LOOP 291
|
||||
# define MATERIAL 292
|
||||
# define MATRIX3 293
|
||||
# define MATRIX4 294
|
||||
# define MODEL 295
|
||||
# define MREF 296
|
||||
# define NORMAL 297
|
||||
# define NURBSCURVE 298
|
||||
# define NURBSSURFACE 299
|
||||
# define OBJECTTYPE 300
|
||||
# define ORDER 301
|
||||
# define OUTTANGENT 302
|
||||
# define POINTLIGHT 303
|
||||
# define POLYGON 304
|
||||
# define REF 305
|
||||
# define RGBA 306
|
||||
# define ROTATE 307
|
||||
# define ROTX 308
|
||||
# define ROTY 309
|
||||
# define ROTZ 310
|
||||
# define SANIM 311
|
||||
# define SCALAR 312
|
||||
# define SCALE 313
|
||||
# define SEQUENCE 314
|
||||
# define SHADING 315
|
||||
# define SWITCH 316
|
||||
# define SWITCHCONDITION 317
|
||||
# define TABLE 318
|
||||
# define TABLE_V 319
|
||||
# define TAG 320
|
||||
# define TANGENT 321
|
||||
# define TEXLIST 322
|
||||
# define TEXTURE 323
|
||||
# define TLENGTHS 324
|
||||
# define TRANSFORM 325
|
||||
# define TRANSLATE 326
|
||||
# define TREF 327
|
||||
# define TRIANGLEFAN 328
|
||||
# define TRIANGLESTRIP 329
|
||||
# define TRIM 330
|
||||
# define TXT 331
|
||||
# define UKNOTS 332
|
||||
# define UV 333
|
||||
# define VKNOTS 334
|
||||
# define VERTEX 335
|
||||
# define VERTEXANIM 336
|
||||
# define VERTEXPOOL 337
|
||||
# define VERTEXREF 338
|
||||
# define XFMANIM 339
|
||||
# define XFMSANIM 340
|
||||
# define START_EGG 341
|
||||
# define START_GROUP_BODY 342
|
||||
# define START_TEXTURE_BODY 343
|
||||
# define START_PRIMITIVE_BODY 344
|
||||
|
||||
|
||||
extern YYSTYPE eggyylval;
|
||||
|
@ -146,7 +146,7 @@ egg_cleanup_parser() {
|
||||
%token <_ulong> ULONG
|
||||
%token <_string> STRING
|
||||
|
||||
%token BEZIERCURVE BFACE BILLBOARD BILLBOARDCENTER BUNDLE CLOSED
|
||||
%token BEZIERCURVE BFACE BILLBOARD BILLBOARDCENTER BINORMAL BUNDLE CLOSED
|
||||
%token COLLIDE COMMENT COMPONENT
|
||||
%token COORDSYSTEM CV DART
|
||||
%token DNORMAL DRGBA DUV DXYZ DCS DISTANCE DTREF
|
||||
@ -157,7 +157,7 @@ egg_cleanup_parser() {
|
||||
%token NURBSCURVE NURBSSURFACE OBJECTTYPE ORDER
|
||||
%token OUTTANGENT POINTLIGHT POLYGON REF RGBA ROTATE ROTX ROTY ROTZ
|
||||
%token SANIM SCALAR SCALE SEQUENCE SHADING SWITCH SWITCHCONDITION
|
||||
%token TABLE TABLE_V TAG TEXLIST TEXTURE TLENGTHS TRANSFORM TRANSLATE
|
||||
%token TABLE TABLE_V TAG TANGENT TEXLIST TEXTURE TLENGTHS TRANSFORM TRANSLATE
|
||||
%token TREF TRIANGLEFAN TRIANGLESTRIP
|
||||
%token TRIM TXT UKNOTS UV VKNOTS VERTEX VERTEXANIM
|
||||
%token VERTEXPOOL VERTEXREF
|
||||
@ -952,6 +952,22 @@ vertex_uv_body:
|
||||
real real
|
||||
{
|
||||
DCAST(EggVertexUV, egg_stack.back())->set_uv(TexCoordd($1, $2));
|
||||
}
|
||||
| vertex_uv_body TANGENT '{' real real real '}'
|
||||
{
|
||||
if (DCAST(EggVertexUV, egg_stack.back())->has_tangent()) {
|
||||
eggyywarning("Ignoring repeated tangent");
|
||||
} else {
|
||||
DCAST(EggVertexUV, egg_stack.back())->set_tangent(Normald($4, $5, $6));
|
||||
}
|
||||
}
|
||||
| vertex_uv_body BINORMAL '{' real real real '}'
|
||||
{
|
||||
if (DCAST(EggVertexUV, egg_stack.back())->has_binormal()) {
|
||||
eggyywarning("Ignoring repeated binormal");
|
||||
} else {
|
||||
DCAST(EggVertexUV, egg_stack.back())->set_binormal(Normald($4, $5, $6));
|
||||
}
|
||||
}
|
||||
| vertex_uv_body DUV string '{' real real '}'
|
||||
{
|
||||
|
@ -371,21 +371,85 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
|
||||
// Now, is our parent node a GeomNode, or just an ordinary
|
||||
// PandaNode? If it's a GeomNode, we can add the new Geom directly
|
||||
// to our parent; otherwise, we need to create a new node.
|
||||
PT(GeomNode) geom_node;
|
||||
if (parent->is_geom_node() && !render_state->_hidden) {
|
||||
DCAST(GeomNode, parent)->add_geom(geom, render_state->_state);
|
||||
geom_node = DCAST(GeomNode, parent);
|
||||
|
||||
} else {
|
||||
PT(GeomNode) geom_node = new GeomNode(egg_bin->get_name());
|
||||
geom_node = new GeomNode(egg_bin->get_name());
|
||||
if (render_state->_hidden) {
|
||||
parent->add_stashed(geom_node);
|
||||
} else {
|
||||
parent->add_child(geom_node);
|
||||
}
|
||||
geom_node->add_geom(geom, render_state->_state);
|
||||
}
|
||||
|
||||
geom_node->add_geom(geom, render_state->_state);
|
||||
if (egg_show_normals) {
|
||||
show_normals(vertex_pool, geom_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggLoader::show_normals
|
||||
// Access: Private
|
||||
// Description: In the presence of egg-show-normals, generate some
|
||||
// additional geometry to represent the normals,
|
||||
// tangents, and binormals of each vertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggLoader::
|
||||
show_normals(EggVertexPool *vertex_pool, GeomNode *geom_node) {
|
||||
PT(GeomPrimitive) primitive = new GeomLines(Geom::UH_static);
|
||||
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3cp();
|
||||
PT(GeomVertexData) vertex_data =
|
||||
new GeomVertexData(vertex_pool->get_name(), format, Geom::UH_static);
|
||||
|
||||
GeomVertexWriter vertex(vertex_data, InternalName::get_vertex());
|
||||
GeomVertexWriter color(vertex_data, InternalName::get_color());
|
||||
|
||||
EggVertexPool::const_iterator vi;
|
||||
for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
|
||||
EggVertex *vert = (*vi);
|
||||
LPoint3d pos = vert->get_pos3();
|
||||
|
||||
if (vert->has_normal()) {
|
||||
vertex.add_data3f(LCAST(float, pos));
|
||||
vertex.add_data3f(LCAST(float, pos + vert->get_normal() * egg_normal_scale));
|
||||
color.add_data4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
color.add_data4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
primitive->add_next_vertices(2);
|
||||
primitive->close_primitive();
|
||||
}
|
||||
|
||||
// Also look for tangents and binormals in each texture coordinate
|
||||
// set.
|
||||
EggVertex::const_uv_iterator uvi;
|
||||
for (uvi = vert->uv_begin(); uvi != vert->uv_end(); ++uvi) {
|
||||
EggVertexUV *uv_obj = (*uvi);
|
||||
if (uv_obj->has_tangent()) {
|
||||
vertex.add_data3f(LCAST(float, pos));
|
||||
vertex.add_data3f(LCAST(float, pos + uv_obj->get_tangent() * egg_normal_scale));
|
||||
color.add_data4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
color.add_data4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
primitive->add_next_vertices(2);
|
||||
primitive->close_primitive();
|
||||
}
|
||||
if (uv_obj->has_binormal()) {
|
||||
vertex.add_data3f(LCAST(float, pos));
|
||||
vertex.add_data3f(LCAST(float, pos + uv_obj->get_binormal() * egg_normal_scale));
|
||||
color.add_data4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
color.add_data4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
primitive->add_next_vertices(2);
|
||||
primitive->close_primitive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
PT(Geom) geom = new Geom;
|
||||
geom->set_vertex_data(vertex_data);
|
||||
geom->add_primitive(primitive);
|
||||
geom_node->add_geom(geom);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1659,8 +1723,8 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
Geom::NT_packed_dabc, Geom::C_color);
|
||||
}
|
||||
|
||||
vector_string uv_names;
|
||||
vertex_pool->get_uv_names(uv_names);
|
||||
vector_string uv_names, tbn_names;
|
||||
vertex_pool->get_uv_names(uv_names, tbn_names);
|
||||
vector_string::const_iterator ni;
|
||||
for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
|
||||
string name = (*ni);
|
||||
@ -1669,8 +1733,19 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
}
|
||||
PT(InternalName) iname = InternalName::get_texcoord_name(name);
|
||||
array_format->add_column
|
||||
(iname, 2,
|
||||
Geom::NT_float32, Geom::C_texcoord);
|
||||
(iname, 2, Geom::NT_float32, Geom::C_texcoord);
|
||||
}
|
||||
for (ni = tbn_names.begin(); ni != tbn_names.end(); ++ni) {
|
||||
string name = (*ni);
|
||||
if (name == "default") {
|
||||
name = string();
|
||||
}
|
||||
PT(InternalName) iname = InternalName::get_tangent_name(name);
|
||||
array_format->add_column
|
||||
(iname, 3, Geom::NT_float32, Geom::C_vector);
|
||||
iname = InternalName::get_binormal_name(name);
|
||||
array_format->add_column
|
||||
(iname, 3, Geom::NT_float32, Geom::C_vector);
|
||||
}
|
||||
|
||||
PT(GeomVertexFormat) temp_format = new GeomVertexFormat(array_format);
|
||||
@ -1867,6 +1942,19 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
gvw.add_data2f(LCAST(float, duv));
|
||||
}
|
||||
}
|
||||
|
||||
// Also add the tangent and binormal, if present.
|
||||
if (egg_uv->has_tangent() && egg_uv->has_binormal()) {
|
||||
PT(InternalName) iname = InternalName::get_tangent_name(name);
|
||||
gvw.set_column(iname);
|
||||
if (gvw.has_column()) {
|
||||
LVector3d tangent = egg_uv->get_tangent();
|
||||
LVector3d binormal = egg_uv->get_binormal();
|
||||
gvw.add_data3f(LCAST(float, tangent));
|
||||
gvw.set_column(InternalName::get_binormal_name(name));
|
||||
gvw.add_data3f(LCAST(float, binormal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dynamic) {
|
||||
|
@ -105,7 +105,9 @@ private:
|
||||
GeomPrimitive::ShadeModel _shade_model;
|
||||
};
|
||||
typedef pmap<PrimitiveUnifier, PT(GeomPrimitive) > Primitives;
|
||||
|
||||
|
||||
void show_normals(EggVertexPool *vertex_pool, GeomNode *geom_node);
|
||||
|
||||
void make_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent,
|
||||
const LMatrix4d &mat);
|
||||
void make_old_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent,
|
||||
|
@ -136,6 +136,19 @@ get_tangent() {
|
||||
return _tangent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_tangent_name
|
||||
// Access: Published, Static
|
||||
// Description: Returns the InternalName "tangent.name", where name
|
||||
// is the supplied string. This is the column header
|
||||
// for the tangent associated with the named texture
|
||||
// coordinate set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(InternalName) InternalName::
|
||||
get_tangent_name(const string &name) {
|
||||
return get_tangent()->append(name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_binormal
|
||||
// Access: Published, Static
|
||||
@ -155,6 +168,19 @@ get_binormal() {
|
||||
return _binormal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_binormal_name
|
||||
// Access: Published, Static
|
||||
// Description: Returns the InternalName "binormal.name", where name
|
||||
// is the supplied string. This is the column header
|
||||
// for the binormal associated with the named texture
|
||||
// coordinate set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(InternalName) InternalName::
|
||||
get_binormal_name(const string &name) {
|
||||
return get_binormal()->append(name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_texcoord
|
||||
// Access: Published, Static
|
||||
|
@ -67,7 +67,9 @@ PUBLISHED:
|
||||
INLINE static PT(InternalName) get_vertex();
|
||||
INLINE static PT(InternalName) get_normal();
|
||||
INLINE static PT(InternalName) get_tangent();
|
||||
INLINE static PT(InternalName) get_tangent_name(const string &name);
|
||||
INLINE static PT(InternalName) get_binormal();
|
||||
INLINE static PT(InternalName) get_binormal_name(const string &name);
|
||||
INLINE static PT(InternalName) get_texcoord();
|
||||
INLINE static PT(InternalName) get_texcoord_name(const string &name);
|
||||
INLINE static PT(InternalName) get_color();
|
||||
|
@ -87,6 +87,18 @@ add_normals_options() {
|
||||
("nn", "", 48,
|
||||
"Preserve normals exactly as they are. This is the default.",
|
||||
&EggBase::dispatch_normals, NULL, &preserve);
|
||||
|
||||
add_option
|
||||
("tbn", "name", 48,
|
||||
"Compute tangent and binormal for the named texture coordinate "
|
||||
"set(s). The name may include wildcard characters such as * and ?; "
|
||||
"use \"*\" to recompute tangent and binormal for all texture coordinate "
|
||||
"sets. "
|
||||
"The normal must already exist or have been computed via one of the "
|
||||
"above options. The tangent and binormal are used to implement "
|
||||
"bump mapping and related texture-based lighting effects. This option "
|
||||
"may be repeated as necessary to name multiple texture coordinate sets.",
|
||||
&EggBase::dispatch_vector_string, NULL, &_tbn_names);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -66,6 +66,7 @@ protected:
|
||||
};
|
||||
NormalsMode _normals_mode;
|
||||
double _normals_threshold;
|
||||
vector_string _tbn_names;
|
||||
|
||||
bool _got_transform;
|
||||
LMatrix4d _transform;
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "string_utils.h"
|
||||
#include "compose_matrix.h"
|
||||
#include "globPattern.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggWriter::Constructor
|
||||
@ -161,6 +162,14 @@ post_process_egg_file() {
|
||||
// Do nothing.
|
||||
break;
|
||||
}
|
||||
|
||||
for (vector_string::const_iterator si = _tbn_names.begin();
|
||||
si != _tbn_names.end();
|
||||
++si) {
|
||||
GlobPattern uv_name(*si);
|
||||
nout << "Computing tangent and binormal for \"" << uv_name << "\"\n";
|
||||
_data->recompute_tangent_binormal(uv_name);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user