add explicit support for shear to the scene graph

This commit is contained in:
David Rose 2003-07-23 23:03:04 +00:00
parent 46f3c11a34
commit 344ca11ffd
46 changed files with 1192 additions and 665 deletions

View File

@ -19,7 +19,7 @@
#include "animChannel.h"
#include <compose_matrix.h>
#include "compose_matrix.h"
// Tell GCC that we'll take care of the instantiation explicitly here.
#ifdef __GNUC__
@ -33,9 +33,9 @@
////////////////////////////////////////////////////////////////////
void ACMatrixSwitchType::
output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) {
LVecBase3f scale, hpr, translate;
if (decompose_matrix(value, scale, hpr, translate)) {
if (!scale.almost_equal(LVecBase3f(1.0f,1.0f,1.0f))) {
LVecBase3f scale, shear, hpr, translate;
if (decompose_matrix(value, scale, shear, hpr, translate)) {
if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
if (IS_NEARLY_EQUAL(scale[0], scale[1]) &&
IS_NEARLY_EQUAL(scale[1], scale[2])) {
out << " scale " << scale[0];
@ -43,6 +43,9 @@ output_value(ostream &out, const ACMatrixSwitchType::ValueType &value) {
out << " scale " << scale;
}
}
if (!shear.almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) {
out << " shear " << shear;
}
if (!hpr.almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) {
out << " hpr " << hpr;

View File

@ -77,11 +77,12 @@ clear_table(char table_id) {
// Access: Protected, Static
// Description: Returns the table ID associated with the indicated
// table index number. This is the letter 'i', 'j',
// 'k', 'h', 'p', 'r', 'x', 'y', or 'z'.
// 'k', 'a', 'b', 'c', 'h', 'p', 'r', 'x', 'y', or 'z'.
////////////////////////////////////////////////////////////////////
INLINE char AnimChannelMatrixXfmTable::
get_table_id(int table_index) {
return _table_ids[table_index];
nassertr(table_index >= 0 && table_index < num_matrix_components, '\0');
return matrix_component_letters[table_index];
}
@ -93,6 +94,7 @@ get_table_id(int table_index) {
////////////////////////////////////////////////////////////////////
INLINE float AnimChannelMatrixXfmTable::
get_default_value(int table_index) {
return _default_values[table_index];
nassertr(table_index >= 0 && table_index < num_matrix_components, 0.0);
return matrix_component_defaults[table_index];
}

View File

@ -21,24 +21,16 @@
#include "animBundle.h"
#include "config_chan.h"
#include <compose_matrix.h>
#include <indent.h>
#include <datagram.h>
#include <datagramIterator.h>
#include <bamReader.h>
#include <bamWriter.h>
#include <fftCompressor.h>
#include "compose_matrix.h"
#include "indent.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "fftCompressor.h"
TypeHandle AnimChannelMatrixXfmTable::_type_handle;
const char
AnimChannelMatrixXfmTable::_table_ids[AnimChannelMatrixXfmTable::num_tables] =
{ 'i', 'j', 'k', 'h', 'p', 'r', 'x', 'y', 'z' };
const float
AnimChannelMatrixXfmTable::_default_values[AnimChannelMatrixXfmTable::num_tables] =
{ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixXfmTable::Constructor
// Access: Public
@ -66,7 +58,7 @@ AnimChannelMatrixXfmTable(void)
////////////////////////////////////////////////////////////////////
bool AnimChannelMatrixXfmTable::
has_changed(int last_frame, int this_frame) {
for (int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
if (_tables[i].size() > 1) {
if (_tables[i][last_frame % _tables[i].size()] !=
_tables[i][this_frame % _tables[i].size()]) {
@ -85,9 +77,9 @@ has_changed(int last_frame, int this_frame) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
get_value(int frame, LMatrix4f &mat) {
float components[num_tables];
float components[num_matrix_components];
for (int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
if (_tables[i].empty()) {
components[i] = get_default_value(i);
} else {
@ -106,12 +98,12 @@ get_value(int frame, LMatrix4f &mat) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
get_value_no_scale(int frame, LMatrix4f &mat) {
float components[num_tables];
float components[num_matrix_components];
components[0] = 1.0f;
components[1] = 1.0f;
components[2] = 1.0f;
for (int i = 3; i < num_tables; i++) {
for (int i = 3; i < num_matrix_components; i++) {
if (_tables[i].empty()) {
components[i] = get_default_value(i);
} else {
@ -147,7 +139,7 @@ get_scale(int frame, float scale[3]) {
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
clear_all_tables() {
for (int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
_tables[i] = NULL;
}
}
@ -191,7 +183,7 @@ write(ostream &out, int indent_level) const {
// Write a list of all the sub-tables that have data.
bool found_any = false;
for (int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
if (!_tables[i].empty()) {
out << get_table_id(i) << _tables[i].size();
found_any = true;
@ -216,12 +208,12 @@ write(ostream &out, int indent_level) const {
// Function: AnimChannelMatrixXfmTable::get_table_index
// Access: Protected, Static
// Description: Returns the table index number, a value between 0 and
// num_tables, that corresponds to the indicate table
// num_matrix_components, that corresponds to the indicate table
// id. Returns -1 if the table id is invalid.
////////////////////////////////////////////////////////////////////
int AnimChannelMatrixXfmTable::
get_table_index(char table_id) {
for (int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
if (table_id == get_table_id(i)) {
return i;
}
@ -237,8 +229,7 @@ get_table_index(char table_id) {
// the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
write_datagram(BamWriter *manager, Datagram &me)
{
write_datagram(BamWriter *manager, Datagram &me) {
AnimChannelMatrix::write_datagram(manager, me);
if (compress_channels && !FFTCompressor::is_compression_available()) {
@ -250,7 +241,7 @@ write_datagram(BamWriter *manager, Datagram &me)
me.add_bool(compress_channels);
if (!compress_channels) {
// Write out everything uncompressed, as a stream of floats.
for(int i = 0; i < num_tables; i++) {
for (int i = 0; i < num_matrix_components; i++) {
me.add_uint16(_tables[i].size());
for(int j = 0; j < (int)_tables[i].size(); j++) {
me.add_float32(_tables[i][j]);
@ -264,9 +255,9 @@ write_datagram(BamWriter *manager, Datagram &me)
compressor.set_quality(compress_chan_quality);
compressor.write_header(me);
// First, write out the scales.
// First, write out the scales and shears.
int i;
for(i = 0; i < 3; i++) {
for (i = 0; i < 6; i++) {
compressor.write_reals(me, _tables[i], _tables[i].size());
}
@ -274,18 +265,18 @@ write_datagram(BamWriter *manager, Datagram &me)
// a HPR array.
vector_LVecBase3f hprs;
int hprs_length =
max(max(_tables[3].size(), _tables[4].size()), _tables[5].size());
max(max(_tables[6].size(), _tables[7].size()), _tables[8].size());
hprs.reserve(hprs_length);
for (i = 0; i < hprs_length; i++) {
float h = _tables[3].empty() ? 0.0f : _tables[3][i % _tables[3].size()];
float p = _tables[4].empty() ? 0.0f : _tables[4][i % _tables[4].size()];
float r = _tables[5].empty() ? 0.0f : _tables[5][i % _tables[5].size()];
float h = _tables[6].empty() ? 0.0f : _tables[6][i % _tables[6].size()];
float p = _tables[7].empty() ? 0.0f : _tables[7][i % _tables[7].size()];
float r = _tables[8].empty() ? 0.0f : _tables[8][i % _tables[8].size()];
hprs.push_back(LVecBase3f(h, p, r));
}
compressor.write_hprs(me, &hprs[0], hprs_length);
// And now the translations.
for(i = 6; i < 9; i++) {
for(i = 9; i < num_matrix_components; i++) {
compressor.write_reals(me, _tables[i], _tables[i].size());
}
}
@ -300,21 +291,26 @@ write_datagram(BamWriter *manager, Datagram &me)
// place
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
fillin(DatagramIterator& scan, BamReader* manager)
{
fillin(DatagramIterator &scan, BamReader *manager) {
AnimChannelMatrix::fillin(scan, manager);
bool wrote_compressed = scan.get_bool();
if (!wrote_compressed) {
// Regular floats.
for(int i = 0; i < num_tables; i++) {
int size = scan.get_uint16();
PTA_float ind_table;
for(int j = 0; j < size; j++) {
ind_table.push_back(scan.get_float32());
for (int i = 0; i < num_matrix_components; i++) {
if (manager->get_file_minor_ver() < 6 && i >= 3 && i < 6) {
// Old bam files didn't store a shear component.
_tables[i].clear();
} else {
int size = scan.get_uint16();
PTA_float ind_table;
for (int j = 0; j < size; j++) {
ind_table.push_back(scan.get_float32());
}
_tables[i] = ind_table;
}
_tables[i] = ind_table;
}
} else {
@ -330,32 +326,45 @@ fillin(DatagramIterator& scan, BamReader* manager)
compressor.read_header(scan);
int i;
// First, read in the scales.
for(i = 0; i < 3; i++) {
PTA_float ind_table=PTA_float::empty_array(0);
// First, read in the scales and shears.
for (i = 0; i < 3; i++) {
PTA_float ind_table = PTA_float::empty_array(0);
compressor.read_reals(scan, ind_table.v());
_tables[i] = ind_table;
}
if (manager->get_file_minor_ver() < 6) {
// Old bam files didn't store a shear.
_tables[3].clear();
_tables[4].clear();
_tables[5].clear();
} else {
for (i = 3; i < 6; i++) {
PTA_float ind_table = PTA_float::empty_array(0);
compressor.read_reals(scan, ind_table.v());
_tables[i] = ind_table;
}
}
// Read in the HPR array and store it back in the joint angles.
vector_LVecBase3f hprs;
compressor.read_hprs(scan, hprs);
PTA_float h_table=PTA_float::empty_array(hprs.size());
PTA_float p_table=PTA_float::empty_array(hprs.size());
PTA_float r_table=PTA_float::empty_array(hprs.size());
PTA_float h_table = PTA_float::empty_array(hprs.size());
PTA_float p_table = PTA_float::empty_array(hprs.size());
PTA_float r_table = PTA_float::empty_array(hprs.size());
for (i = 0; i < (int)hprs.size(); i++) {
h_table[i] = hprs[i][0];
p_table[i] = hprs[i][1];
r_table[i] = hprs[i][2];
}
_tables[3] = h_table;
_tables[4] = p_table;
_tables[5] = r_table;
_tables[6] = h_table;
_tables[7] = p_table;
_tables[8] = r_table;
// Now read in the translations.
for (i = 6; i < 9; i++) {
PTA_float ind_table=PTA_float::empty_array(0);
for (i = 9; i < num_matrix_components; i++) {
PTA_float ind_table = PTA_float::empty_array(0);
compressor.read_reals(scan, ind_table.v());
_tables[i] = ind_table;
}
@ -365,11 +374,11 @@ fillin(DatagramIterator& scan, BamReader* manager)
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixXfmTable::make_AnimChannelMatrixXfmTable
// Access: Protected
// Description: Factory method to generate a AnimChannelMatrixXfmTable object
// Description: Factory method to generate an
// AnimChannelMatrixXfmTable object.
////////////////////////////////////////////////////////////////////
TypedWritable* AnimChannelMatrixXfmTable::
make_AnimChannelMatrixXfmTable(const FactoryParams &params)
{
TypedWritable *AnimChannelMatrixXfmTable::
make_AnimChannelMatrixXfmTable(const FactoryParams &params) {
AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable;
DatagramIterator scan;
BamReader *manager;
@ -382,11 +391,11 @@ make_AnimChannelMatrixXfmTable(const FactoryParams &params)
////////////////////////////////////////////////////////////////////
// Function: AnimChannelMatrixXfmTable::register_with_factory
// Access: Public, Static
// Description: Factory method to generate a AnimChannelMatrixXfmTable object
// Description: Factory method to generate an
// AnimChannelMatrixXfmTable object.
////////////////////////////////////////////////////////////////////
void AnimChannelMatrixXfmTable::
register_with_read_factory(void)
{
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable);
}

View File

@ -19,12 +19,13 @@
#ifndef ANIMCHANNELMATRIXXFMTABLE_H
#define ANIMCHANNELMATRIXXFMTABLE_H
#include <pandabase.h>
#include "pandabase.h"
#include "animChannel.h"
#include <pointerToArray.h>
#include <pta_float.h>
#include "pointerToArray.h"
#include "pta_float.h"
#include "compose_matrix.h"
////////////////////////////////////////////////////////////////////
// Class : AnimChannelMatrixXfmTable
@ -59,13 +60,7 @@ protected:
static int get_table_index(char table_id);
INLINE static float get_default_value(int table_index);
enum { num_tables = 9 };
CPTA_float _tables[num_tables];
private:
static const char _table_ids[num_tables];
static const float _default_values[num_tables];
CPTA_float _tables[num_matrix_components];
public:
static void register_with_read_factory(void);

View File

@ -19,11 +19,11 @@
#include "movingPartMatrix.h"
#include <compose_matrix.h>
#include <datagram.h>
#include <datagramIterator.h>
#include <bamReader.h>
#include <bamWriter.h>
#include "compose_matrix.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
#include "bamWriter.h"
// Tell GCC that we'll take care of the instantiation explicitly here.
#ifdef __GNUC__
@ -93,6 +93,8 @@ get_blend_value(const PartBundle *root) {
// resulting matrix to eliminate artificially-introduced scales,
// and then reapply the scales.
// Perhaps we should treat shear the same as a scale here?
_value = 0.0f;
LVector3f scale(0.0f, 0.0f, 0.0f);
float net = 0.0f;
@ -124,9 +126,9 @@ get_blend_value(const PartBundle *root) {
// Now rebuild the matrix with the correct scale values.
LVector3f false_scale, hpr, translate;
decompose_matrix(_value, false_scale, hpr, translate);
compose_matrix(_value, scale, hpr, translate);
LVector3f false_scale, shear, hpr, translate;
decompose_matrix(_value, false_scale, shear, hpr, translate);
compose_matrix(_value, scale, shear, hpr, translate);
}
}
}

View File

@ -19,7 +19,7 @@
#ifndef MOVINGPARTMATRIX_H
#define MOVINGPARTMATRIX_H
#include <pandabase.h>
#include "pandabase.h"
#include "movingPart.h"
#include "animChannel.h"

View File

@ -19,7 +19,6 @@
#include "characterJoint.h"
#include "config_char.h"
#include "compose_matrix.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"

View File

@ -1227,18 +1227,19 @@ GROUPING ENTRIES
<Xfm$Anim> name {
<Scalar> fps { 24 }
<Char*> order { sphrt }
<Char*> contents { ijkphrxyz }
<Char*> contents { ijkabcphrxyz }
<V> { values }
}
This is a table of matrix transforms, one per frame, such as may
be applied to a joint. The "contents" string consists of a subset
of the letters "ijkphrxyz", where each letter corresponds to a
of the letters "ijkabcphrxyz", where each letter corresponds to a
column of the table; <V> is a list of numbers of length(contents)
* num_frames. Each letter of the contents string corresponds to a
type of transformation:
i, j, k - scale in x, y, z directions, respectively
a, b, c - shear in xy, xz, and yz planes, respectively
p, h, r - rotate by pitch, heading, roll
x, y, z - translate in x, y, z directions
@ -1248,7 +1249,7 @@ GROUPING ENTRIES
string. The order the transforms are applied is defined by the
order string:
s - all scale transforms
s - all scale and shear transforms
p, h, r - individual rotate transforms
t - all translation transforms

View File

@ -51,8 +51,8 @@
#include "eggXfmAnimData.h"
#include "eggXfmSAnim.h"
#include <dconfig.h>
#include <get_config_path.h>
#include "dconfig.h"
#include "get_config_path.h"
Configure(config_egg);
NotifyCategoryDef(egg, "");

View File

@ -19,8 +19,8 @@
#ifndef CONFIG_EGG_H
#define CONFIG_EGG_H
#include <pandabase.h>
#include <notifyCategoryProxy.h>
#include "pandabase.h"
#include "notifyCategoryProxy.h"
class DSearchPath;

View File

@ -22,10 +22,10 @@
#include "eggMiscFuncs.h"
#include "config_egg.h"
#include <indent.h>
#include <luse.h>
#include <lmatrix.h>
#include <compose_matrix.h>
#include "indent.h"
#include "luse.h"
#include "lmatrix.h"
#include "compose_matrix.h"
TypeHandle EggXfmAnimData::_type_handle;
@ -94,6 +94,7 @@ EggXfmAnimData(const EggXfmSAnim &convert_from)
void EggXfmAnimData::
get_value(int row, LMatrix4d &mat) const {
LVector3d scale(1.0, 1.0, 1.0);
LVector3d shear(0.0, 0.0, 0.0);
LVector3d hpr(0.0, 0.0, 0.0);
LVector3d translate(0.0, 0.0, 0.0);
@ -113,6 +114,18 @@ get_value(int row, LMatrix4d &mat) const {
scale[2] = value;
break;
case 'a':
shear[0] = value;
break;
case 'b':
shear[1] = value;
break;
case 'c':
shear[2] = value;
break;
case 'h':
hpr[0] = value;
break;
@ -143,8 +156,8 @@ get_value(int row, LMatrix4d &mat) const {
}
}
// So now we've got the nine components; build a matrix.
EggXfmSAnim::compose_with_order(mat, scale, hpr, translate, get_order(),
// So now we've got the twelve components; build a matrix.
EggXfmSAnim::compose_with_order(mat, scale, shear, hpr, translate, get_order(),
_coordsys);
}
@ -221,26 +234,28 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
egg_cat.error()
<< "Transform from " << _coordsys << " to " << to_cs
<< " failed!\n";
LVector3d scale, hpr, trans;
bool d = decompose_matrix(orig_mat, scale, hpr, trans, _coordsys);
LVector3d scale, shear, hpr, trans;
bool d = decompose_matrix(orig_mat, scale, shear, hpr, trans, _coordsys);
egg_cat.error(false)
<< "orig:\n" << orig_mat
<< "d = " << d
<< "\n scale: " << scale
<< "\n shear: " << shear
<< "\n hpr: " << hpr
<< "\n trans: " << trans << "\n";
LMatrix4d new_mat = inv1 * orig_mat * mat;
d = decompose_matrix(new_mat, scale, hpr, trans, to_cs);
d = decompose_matrix(new_mat, scale, shear, hpr, trans, to_cs);
egg_cat.error(false)
<< "new:\n" << new_mat
<< "d = " << d
<< "\n scale: " << scale
<< "\n shear: " << shear
<< "\n hpr: " << hpr
<< "\n trans: " << trans << "\n";
}
// If this assertion fails, we attempted to transform by a skew
// If this assertion fails, we attempted to transform by non-affine
// matrix or some such thing that cannot be represented in an anim
// file.
nassertv(result);

View File

@ -19,7 +19,7 @@
#ifndef EGGXFMANIMDATA_H
#define EGGXFMANIMDATA_H
#include <pandabase.h>
#include "pandabase.h"
#include "eggAnimData.h"
#include "eggXfmSAnim.h"

View File

@ -37,11 +37,6 @@ TypeHandle EggXfmSAnim::_type_handle;
const string EggXfmSAnim::_standard_order_legacy = "sphrt";
const string EggXfmSAnim::_standard_order_hpr_fix = "srpht";
// These are the table ID's of all tables we support, in the order we
// expect to write them to the egg file.
const string EggXfmSAnim::_table_ids = "ijkhprxyz";
const int EggXfmSAnim::_num_table_ids = 9;
////////////////////////////////////////////////////////////////////
// Function: EggXfmSAnim::Conversion constructor
@ -181,8 +176,8 @@ write(ostream &out, int indent_level) const {
// write out all the non-table children first, then write out the
// table children in our expected order. (Normally there are only
// table children.)
EggSAnimData *tables[_num_table_ids];
memset(tables, 0, sizeof(EggSAnimData *) * _num_table_ids);
EggSAnimData *tables[num_matrix_components];
memset(tables, 0, sizeof(EggSAnimData *) * num_matrix_components);
const_iterator ci;
for (ci = begin(); ci != end(); ++ci) {
@ -193,9 +188,10 @@ write(ostream &out, int indent_level) const {
// Each child SAnimData table should have a one-letter name.
nassertv(sanim->get_name().length() == 1);
char name = sanim->get_name()[0];
size_t index = _table_ids.find(name);
nassertv(index != string::npos);
if (index != string::npos) {
char *p = strchr(matrix_component_letters, name);
nassertv(p != (char *)NULL);
if (p != (char *)NULL) {
int index = p - matrix_component_letters;
nassertv(tables[index] == (EggSAnimData *)NULL);
tables[index] = sanim;
}
@ -206,7 +202,7 @@ write(ostream &out, int indent_level) const {
}
// Now write out the table children in our normal order.
for (int i = 0; i < _num_table_ids; i++) {
for (int i = 0; i < num_matrix_components; i++) {
if (tables[i] != (EggSAnimData *)NULL) {
tables[i]->write(out, indent_level + 2);
}
@ -227,6 +223,7 @@ write(ostream &out, int indent_level) const {
void EggXfmSAnim::
compose_with_order(LMatrix4d &mat,
const LVecBase3d &scale,
const LVecBase3d &shear,
const LVecBase3d &hpr,
const LVecBase3d &trans,
const string &order,
@ -247,7 +244,7 @@ compose_with_order(LMatrix4d &mat,
for (pi = order.begin(); pi != order.end(); ++pi) {
switch (*pi) {
case 's':
mat = mat * LMatrix4d::scale_mat(scale);
mat = mat * LMatrix4d::scale_shear_mat(scale, shear, cs);
break;
case 'h':
@ -318,11 +315,12 @@ get_num_rows() const {
// table of matrices. It is an error to call this if
// any SAnimData children of this node have an improper
// name (e.g. not a single letter, or not one of
// "ijkhprxyz").
// "ijkabchprxyz").
////////////////////////////////////////////////////////////////////
void EggXfmSAnim::
get_value(int row, LMatrix4d &mat) const {
LVector3d scale(1.0, 1.0, 1.0);
LVector3d shear(0.0, 0.0, 0.0);
LVector3d hpr(0.0, 0.0, 0.0);
LVector3d translate(0.0, 0.0, 0.0);
@ -361,6 +359,18 @@ get_value(int row, LMatrix4d &mat) const {
scale[2] = value;
break;
case 'a':
shear[0] = value;
break;
case 'b':
shear[1] = value;
break;
case 'c':
shear[2] = value;
break;
case 'h':
hpr[0] = value;
break;
@ -393,7 +403,7 @@ get_value(int row, LMatrix4d &mat) const {
}
// So now we've got the nine components; build a matrix.
compose_with_order(mat, scale, hpr, translate, get_order(), _coordsys);
compose_with_order(mat, scale, shear, hpr, translate, get_order(), _coordsys);
}
////////////////////////////////////////////////////////////////////
@ -407,90 +417,69 @@ get_value(int row, LMatrix4d &mat) const {
// normalize() first if you are not sure.
//
// The return value is true if the matrix can be
// decomposed and stored as scale, rotate, and
// translate, or false otherwise.
// decomposed and stored as scale, shear, rotate, and
// translate, or false otherwise. The data is set in
// either case.
////////////////////////////////////////////////////////////////////
bool EggXfmSAnim::
set_value(int row, const LMatrix4d &mat) {
nassertr(get_order() == get_standard_order(), false);
LVector3d scale, hpr, translate;
bool result = decompose_matrix(mat, scale, hpr, translate, _coordsys);
if (!result) {
return false;
}
double components[num_matrix_components];
bool add_ok = decompose_matrix(mat, components, _coordsys);
// Sanity check our sub-tables.
#ifndef NDEBUG
int table_length = -1;
int num_tables = 0;
#endif
const_iterator ci;
for (ci = begin(); ci != end(); ++ci) {
if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
EggSAnimData *sanim = DCAST(EggSAnimData, *ci);
for (int i = 0; i < num_matrix_components; i++) {
string name(1, matrix_component_letters[i]);
EggNode *child = find_child(name);
nassertr(child != (EggNode *)NULL &&
child->is_of_type(EggSAnimData::get_class_type()), false);
EggSAnimData *sanim = DCAST(EggSAnimData, child);
#ifndef NDEBUG
num_tables++;
// Each table must have the same length.
if (table_length < 0) {
table_length = sanim->get_num_rows();
} else {
nassertr(sanim->get_num_rows() == table_length, false);
}
#endif
// Each child SAnimData table should have a one-letter name.
nassertr(sanim->get_name().length() == 1, false);
switch (sanim->get_name()[0]) {
case 'i':
sanim->set_value(row, scale[0]);
break;
case 'j':
sanim->set_value(row, scale[1]);
break;
case 'k':
sanim->set_value(row, scale[2]);
break;
case 'h':
sanim->set_value(row, hpr[0]);
break;
case 'p':
sanim->set_value(row, hpr[1]);
break;
case 'r':
sanim->set_value(row, hpr[2]);
break;
case 'x':
sanim->set_value(row, translate[0]);
break;
case 'y':
sanim->set_value(row, translate[1]);
break;
case 'z':
sanim->set_value(row, translate[2]);
break;
default:
// One of the child tables had an invalid name.
nassertr(false, false);
}
// Each table must have the same length.
if (table_length < 0) {
table_length = sanim->get_num_rows();
} else {
nassertr(sanim->get_num_rows() == table_length, false);
}
#endif
sanim->set_value(row, components[i]);
}
nassertr(num_tables == 9, false);
return true;
#ifndef NDEBUG
// Sanity check the result.
LMatrix4d new_mat;
get_value(row, new_mat);
if (!new_mat.almost_equal(mat, 0.005)) {
egg_cat.warning()
<< "After set_row(" << row << ", ...) to:\n";
mat.write(egg_cat.warning(false), 2);
egg_cat.warning(false)
<< "which produces components:\n";
for (int i = 0; i < num_matrix_components; i += 3) {
egg_cat.warning(false)
<< " "
<< matrix_component_letters[i]
<< matrix_component_letters[i + 1]
<< matrix_component_letters[i + 2]
<< ": "
<< components[i] << " "
<< components[i + 1] << " "
<< components[i + 2] << "\n";
}
egg_cat.warning(false)
<< "new mat set was:\n";
new_mat.write(egg_cat.warning(false), 2);
return false;
}
#endif
return add_ok;
}
////////////////////////////////////////////////////////////////////
@ -504,14 +493,13 @@ set_value(int row, const LMatrix4d &mat) {
// table of matrices. It is an error to call this if
// any SAnimData children of this node have an improper
// name (e.g. not a single letter, or not one of
// "ijkhprxyz").
// "ijkabchprxyz").
//
// This function has the further requirement that all
// nine of the subtables must exist and be of the same
// length. Furthermore, the order string must be the
// standard order string, "ijkrphxyz", which matches the
// system compose_matrix() and decompose_matrix()
// functions.
// standard order string, which matches the system
// compose_matrix() and decompose_matrix() functions.
//
// Thus, you probably cannot take an existing
// EggXfmSAnim object and start adding matrices to the
@ -521,21 +509,20 @@ set_value(int row, const LMatrix4d &mat) {
// you on an existing EggXfmSAnim.
//
// This function may fail silently if the matrix cannot
// be decomposed into scale, rotate, and translate. In
// this case, the closest approximation is added to the
// table, and false is returned.
// be decomposed into scale, shear, rotate, and
// translate. In this case, the closest approximation
// is added to the table, and false is returned.
////////////////////////////////////////////////////////////////////
bool EggXfmSAnim::
add_data(const LMatrix4d &mat) {
LVector3d scale, hpr, translate;
bool add_ok = decompose_matrix(mat, scale, hpr, translate, _coordsys);
double components[num_matrix_components];
bool add_ok = decompose_matrix(mat, components, _coordsys);
if (empty()) {
// If we have no children, create all nine tables now.
for (string::const_iterator p = _table_ids.begin();
p != _table_ids.end();
++p) {
EggSAnimData *sanim = new EggSAnimData(string(1, *p));
// If we have no children, create all twelve tables now.
for (int i = 0; i < num_matrix_components; i++) {
char name = matrix_component_letters[i];
EggSAnimData *sanim = new EggSAnimData(string(1, name));
add_child(sanim);
}
@ -547,73 +534,57 @@ add_data(const LMatrix4d &mat) {
#ifndef NDEBUG
int table_length = -1;
int num_tables = 0;
#endif
const_iterator ci;
for (ci = begin(); ci != end(); ++ci) {
if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
EggSAnimData *sanim = DCAST(EggSAnimData, *ci);
for (int i = 0; i < num_matrix_components; i++) {
string name(1, matrix_component_letters[i]);
EggNode *child = find_child(name);
nassertr(child != (EggNode *)NULL &&
child->is_of_type(EggSAnimData::get_class_type()), false);
EggSAnimData *sanim = DCAST(EggSAnimData, child);
#ifndef NDEBUG
num_tables++;
// Each table must have the same length.
if (table_length < 0) {
table_length = sanim->get_num_rows();
} else {
nassertr(sanim->get_num_rows() == table_length, false);
}
#endif
// Each child SAnimData table should have a one-letter name.
nassertr(sanim->get_name().length() == 1, false);
switch (sanim->get_name()[0]) {
case 'i':
sanim->add_data(scale[0]);
break;
case 'j':
sanim->add_data(scale[1]);
break;
case 'k':
sanim->add_data(scale[2]);
break;
case 'h':
sanim->add_data(hpr[0]);
break;
case 'p':
sanim->add_data(hpr[1]);
break;
case 'r':
sanim->add_data(hpr[2]);
break;
case 'x':
sanim->add_data(translate[0]);
break;
case 'y':
sanim->add_data(translate[1]);
break;
case 'z':
sanim->add_data(translate[2]);
break;
default:
// One of the child tables had an invalid name.
nassertr(false, false);
}
// Each table must have the same length.
if (table_length < 0) {
table_length = sanim->get_num_rows();
} else {
nassertr(sanim->get_num_rows() == table_length, false);
}
#endif
sanim->add_data(components[i]);
}
nassertr(num_tables == 9, false);
#ifndef NDEBUG
// Sanity check the result.
LMatrix4d new_mat;
if (table_length >= 0) {
get_value(table_length, new_mat);
} else {
get_value(0, new_mat);
}
if (!new_mat.almost_equal(mat, 0.005)) {
egg_cat.warning()
<< "After add_data():\n";
mat.write(egg_cat.warning(false), 2);
egg_cat.warning(false)
<< "which produces components:\n";
for (int i = 0; i < num_matrix_components; i += 3) {
egg_cat.warning(false)
<< " "
<< matrix_component_letters[i]
<< matrix_component_letters[i + 1]
<< matrix_component_letters[i + 2]
<< ": "
<< components[i] << " "
<< components[i + 1] << " "
<< components[i + 2] << "\n";
}
egg_cat.warning(false)
<< "new mat set was:\n";
new_mat.write(egg_cat.warning(false), 2);
return false;
}
#endif
return add_ok;
}
@ -723,7 +694,7 @@ normalize_by_expanding() {
// are.
int num_tables = 0;
int table_length = 1;
string remaining_tables = "ijkhprxyz";
string remaining_tables = matrix_component_letters;
for (ci = begin(); ci != end(); ++ci) {
if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
@ -746,7 +717,7 @@ normalize_by_expanding() {
}
}
if (num_tables < 9) {
if (num_tables < num_matrix_components) {
// Create new, default, children for each table we lack.
for (size_t p = 0; p < remaining_tables.length(); p++) {
if (remaining_tables[p] != ' ') {

View File

@ -71,6 +71,7 @@ public:
static void compose_with_order(LMatrix4d &mat,
const LVecBase3d &scale,
const LVecBase3d &shear,
const LVecBase3d &hpr,
const LVecBase3d &trans,
const string &order,
@ -94,8 +95,6 @@ private:
static const string _standard_order_legacy;
static const string _standard_order_hpr_fix;
static const string _table_ids;
static const int _num_table_ids;
public:

View File

@ -1275,8 +1275,8 @@ void Lens::
compute_view_hpr() {
if ((_user_flags & UF_view_hpr) == 0) {
const LMatrix4f &view_mat = get_view_mat();
LVecBase3f scale, translate;
decompose_matrix(view_mat, scale, _view_hpr, translate, _cs);
LVecBase3f scale, shear, translate;
decompose_matrix(view_mat, scale, shear, _view_hpr, translate, _cs);
}
adjust_comp_flags(0, CF_view_hpr);
}
@ -1371,7 +1371,9 @@ compute_lens_mat() {
if ((_user_flags & UF_view_mat) == 0) {
if ((_user_flags & UF_view_hpr) != 0) {
compose_matrix(_lens_mat,
LVecBase3f(1.0f, 1.0f, 1.0f), _view_hpr,
LVecBase3f(1.0f, 1.0f, 1.0f),
LVecBase3f(0.0f, 0.0f, 0.0f),
_view_hpr,
LVecBase3f(0.0f, 0.0f, 0.0f), _cs);
} else if ((_user_flags & UF_view_vector) != 0) {

View File

@ -27,5 +27,10 @@
#include "compose_matrix_src.cxx"
const char * const matrix_components = "ijkhprxyz";
const int num_matrix_components = 9;
const char * const matrix_component_letters = "ijkabchprxyz";
const double matrix_component_defaults[num_matrix_components] = {
1.0, 1.0, 1.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0
};

View File

@ -44,17 +44,18 @@
#include "lvec2_ops.h"
#include "lvec3_ops.h"
// These define the standard one-letter names for the components in
// the array-accepting forms of compose_matrix() and
// decompose_matrix().
static const int num_matrix_components = 12;
EXPCL_PANDA extern const char * const matrix_component_letters;
EXPCL_PANDA extern const double matrix_component_defaults[num_matrix_components];
#include "fltnames.h"
#include "compose_matrix_src.h"
#include "dblnames.h"
#include "compose_matrix_src.h"
// These define the standard one-letter names for the components in
// the array-accepting forms of compose_matrix() and
// decompose_matrix().
EXPCL_PANDA extern const char * const matrix_components;
EXPCL_PANDA extern const int num_matrix_components;
#endif

View File

@ -17,6 +17,103 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: compose_matrix
// Description: Computes the 4x4 matrix according to scale, shear,
// rotation, and translation.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
const FLOATNAME(LVecBase3) &hpr,
const FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs) {
FLOATNAME(LMatrix3) upper3;
compose_matrix(upper3, scale, shear, hpr, cs);
mat = FLOATNAME(LMatrix4)(upper3, translate);
}
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat,
const FLOATTYPE components[num_matrix_components],
CoordinateSystem cs) {
FLOATNAME(LVector3) scale(components[0],
components[1],
components[2]);
FLOATNAME(LVector3) shear(components[3],
components[4],
components[5]);
FLOATNAME(LVector3) hpr(components[6],
components[7],
components[8]);
FLOATNAME(LVector3) translate(components[9],
components[10],
components[11]);
compose_matrix(mat, scale, shear, hpr, translate, cs);
}
////////////////////////////////////////////////////////////////////
// Function: decompose_matrix
// Description: Extracts out the components of an affine matrix.
// Returns true if the scale, shear, hpr, and translate
// completely describe the matrix, or false if the
// matrix is not affine.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &shear,
FLOATNAME(LVecBase3) &hpr,
FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs) {
// Get the translation first.
mat.get_row3(translate,3);
if (!decompose_matrix(mat.get_upper_3(), scale, shear, hpr, cs)) {
return false;
}
#ifndef NDEBUG
return mat.get_col(3).almost_equal(FLOATNAME(LVecBase4)(0.0, 0.0, 0.0, 1.0));
#else
return true;
#endif
}
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATTYPE components[num_matrix_components],
CoordinateSystem cs) {
FLOATNAME(LVector3) scale, shear, hpr, translate;
bool result = decompose_matrix(mat, scale, shear, hpr, translate, cs);
components[0] = scale[0];
components[1] = scale[1];
components[2] = scale[2];
components[3] = shear[0];
components[4] = shear[1];
components[5] = shear[2];
components[6] = hpr[0];
components[7] = hpr[1];
components[8] = hpr[2];
components[9] = translate[0];
components[10] = translate[1];
components[11] = translate[2];
return result;
}
// The following functions are deprecated; they have been replaced
// with new versions, above, that accept a shear component as well.
INLINE EXPCL_PANDA void
compose_matrix(FLOATNAME(LMatrix3) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs) {
compose_matrix(mat, scale, FLOATNAME(LVecBase3)(0, 0, 0), hpr, cs);
}
////////////////////////////////////////////////////////////////////
// Function: compose_matrix
// Description: Computes the 4x4 matrix according to scale, rotation,
@ -33,20 +130,16 @@ compose_matrix(FLOATNAME(LMatrix4) &mat,
mat = FLOATNAME(LMatrix4)(upper3, translate);
}
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat,
const FLOATTYPE components[9],
CoordinateSystem cs) {
FLOATNAME(LVector3) scale(components[0],
components[1],
components[2]);
FLOATNAME(LVector3) hpr(components[3],
components[4],
components[5]);
FLOATNAME(LVector3) translate(components[6],
components[7],
components[8]);
compose_matrix(mat, scale, hpr, translate, cs);
INLINE EXPCL_PANDA bool
decompose_matrix(const FLOATNAME(LMatrix3) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs) {
FLOATNAME(LVecBase3) shear;
if (!decompose_matrix(mat, scale, shear, hpr, cs)) {
return false;
}
return shear.almost_equal(FLOATNAME(LVecBase3)::zero());
}
@ -68,49 +161,3 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat,
mat.get_row3(translate,3);
return decompose_matrix(mat.get_upper_3(), scale, hpr, cs);
}
////////////////////////////////////////////////////////////////////
// Function: decompose_matrix
// Description: Extracts out the components of an affine matrix.
// Returns true if the scale, hpr, translate
// completely describe the matrix, or false if there is
// also a shear component or if the matrix is not
// affine.
//
// This flavor of the function accepts an expected roll
// amount. This amount will be used as the roll
// component, rather than attempting to determine roll
// by examining the matrix; this helps alleviate roll
// instability due to roundoff errors or gimbal lock.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &hpr,
FLOATNAME(LVecBase3) &translate,
FLOATTYPE roll,
CoordinateSystem cs) {
// Get the translation first.
mat.get_row3(translate,3);
return decompose_matrix(mat.get_upper_3(), scale, hpr, roll, cs);
}
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATTYPE components[9],
CoordinateSystem cs) {
FLOATNAME(LVector3) scale, hpr, translate;
if (!decompose_matrix(mat, scale, hpr, translate, cs)) {
return false;
}
components[0] = scale[0];
components[1] = scale[1];
components[2] = scale[2];
components[3] = hpr[0];
components[4] = hpr[1];
components[5] = hpr[2];
components[6] = translate[0];
components[7] = translate[1];
components[8] = translate[2];
return true;
}

View File

@ -19,11 +19,13 @@
////////////////////////////////////////////////////////////////////
// Function: compose_matrix
// Description: Computes the 3x3 matrix from scale and rotation.
// Description: Computes the 3x3 matrix from scale, shear, and
// rotation.
////////////////////////////////////////////////////////////////////
void
compose_matrix(FLOATNAME(LMatrix3) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
const FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs) {
@ -31,16 +33,18 @@ compose_matrix(FLOATNAME(LMatrix3) &mat,
// as default until legacy tools are fixed to work with correct way
if (temp_hpr_fix) {
mat.scale_multiply(scale,
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs));
mat =
FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs);
} else {
mat.scale_multiply(scale,
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs));
mat =
FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) *
FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs);
}
}
@ -511,13 +515,15 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
////////////////////////////////////////////////////////////////////
// Function: decompose_matrix
// Description: Extracts out the components of a 3x3 rotation matrix.
// Returns true if the scale and hpr completely describe
// the matrix, or false if there is also a shear
// component or if the matrix is not affine.
// Returns true if successful, or false if there was an
// error. Since a 3x3 matrix always contains an affine
// transform, this should succeed in the normal case;
// singular transforms are not treated as an error.
////////////////////////////////////////////////////////////////////
bool
decompose_matrix(const FLOATNAME(LMatrix3) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &shear,
FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs) {
if (cs == CS_default) {
@ -595,29 +601,28 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat,
<< "after unwind, mat is " << new_mat << "\n";
}
scale[0] = new_mat._m.m._00;
scale[1] = new_mat._m.m._11;
scale[2] = new_mat._m.m._22;
/*
if (is_left_handed) {
scale[0] = -new_mat._m.m._00;
scale[1] = -new_mat._m.m._11;
}
*/
bool has_no_shear =
(fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
scale.set(new_mat(0, 0), new_mat(1, 1), new_mat(2, 2));
/*
if (!has_no_shear) {
linmath_cat.info() << "shear:\n";
new_mat.write(linmath_cat.info(false), 2);
// Normalize the scale out of the shear components, and return the
// shear.
if (scale[0] != 0.0) {
new_mat(0, 1) /= scale[0];
new_mat(0, 2) /= scale[0];
}
*/
if (scale[1] != 0.0) {
new_mat(1, 0) /= scale[1];
new_mat(1, 2) /= scale[1];
}
if (scale[2] != 0.0) {
new_mat(2, 0) /= scale[2];
new_mat(2, 1) /= scale[2];
}
shear.set(new_mat(0, 1) + new_mat(1, 0),
new_mat(2, 0) + new_mat(0, 2),
new_mat(2, 1) + new_mat(1, 2));
return has_no_shear;
return true;
}
////////////////////////////////////////////////////////////////////
@ -632,6 +637,10 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat,
// component, rather than attempting to determine roll
// by examining the matrix; this helps alleviate roll
// instability due to roundoff errors or gimbal lock.
//
// This function is deprecated and will soon be removed,
// especially when the need for temp_hpr_fix is
// eliminated.
////////////////////////////////////////////////////////////////////
bool
decompose_matrix(const FLOATNAME(LMatrix3) &mat,

View File

@ -19,6 +19,49 @@
BEGIN_PUBLISH
EXPCL_PANDA void
compose_matrix(FLOATNAME(LMatrix3) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
const FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs = CS_default);
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
const FLOATNAME(LVecBase3) &hpr,
const FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs = CS_default);
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[num_matrix_components],
CoordinateSystem cs = CS_default);
EXPCL_PANDA bool
decompose_matrix(const FLOATNAME(LMatrix3) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &shear,
FLOATNAME(LVecBase3) &hpr,
CoordinateSystem cs = CS_default);
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &shear,
FLOATNAME(LVecBase3) &hpr,
FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs = CS_default);
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[num_matrix_components],
CoordinateSystem CS = CS_default);
// The following functions are deprecated; they have been replaced
// with new versions, above, that accept a shear component as well.
INLINE EXPCL_PANDA void
compose_matrix(FLOATNAME(LMatrix3) &mat,
const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &hpr,
@ -31,11 +74,7 @@ compose_matrix(FLOATNAME(LMatrix4) &mat,
const FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs = CS_default);
INLINE_LINMATH void
compose_matrix(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[9],
CoordinateSystem cs = CS_default);
EXPCL_PANDA bool
INLINE EXPCL_PANDA bool
decompose_matrix(const FLOATNAME(LMatrix3) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &hpr,
@ -55,18 +94,6 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATNAME(LVecBase3) &translate,
CoordinateSystem cs = CS_default);
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat,
FLOATNAME(LVecBase3) &scale,
FLOATNAME(LVecBase3) &hpr,
FLOATNAME(LVecBase3) &translate,
FLOATTYPE roll,
CoordinateSystem cs);
INLINE_LINMATH bool
decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[9],
CoordinateSystem CS = CS_default);
END_PUBLISH
#include "compose_matrix_src.I"

View File

@ -558,28 +558,6 @@ multiply(const FLOATNAME(LMatrix3) &other1, const FLOATNAME(LMatrix3) &other2) {
MATRIX3_PRODUCT((*this),other1,other2);
}
// this = scale_mat(scale_vector) * other_mat, efficiently
INLINE_LINMATH void FLOATNAME(LMatrix3)::
scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix3) &other_mat) {
#ifdef _DEBUG
assert(&other_mat != this);
#endif
// optimize for 0.0 or 1.0 factors?
_m.m._00 = other_mat._m.m._00 * scale_vector._v.v._0;
_m.m._01 = other_mat._m.m._01 * scale_vector._v.v._0;
_m.m._02 = other_mat._m.m._02 * scale_vector._v.v._0;
_m.m._10 = other_mat._m.m._10 * scale_vector._v.v._1;
_m.m._11 = other_mat._m.m._11 * scale_vector._v.v._1;
_m.m._12 = other_mat._m.m._12 * scale_vector._v.v._1;
_m.m._20 = other_mat._m.m._20 * scale_vector._v.v._2;
_m.m._21 = other_mat._m.m._21 * scale_vector._v.v._2;
_m.m._22 = other_mat._m.m._22 * scale_vector._v.v._2;
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix3::matrix * scalar
// Access: Public
@ -1102,10 +1080,9 @@ scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz) {
// shear in each of the three planes.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
shear_mat(const FLOATNAME(LVecBase3) &shear) {
return FLOATNAME(LMatrix3)(1.0f, 0.0f, 0.0f,
shear._v.v._0, 1.0f, 0.0f,
shear._v.v._1, shear._v.v._2, 1.0f);
shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs) {
return scale_shear_mat(FLOATNAME(LVecBase3)(1.0f, 1.0f, 1.0f),
shear, cs);
}
////////////////////////////////////////////////////////////////////
@ -1115,10 +1092,24 @@ shear_mat(const FLOATNAME(LVecBase3) &shear) {
// shear in each of the three planes.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz) {
return FLOATNAME(LMatrix3)(1.0f, 0.0f, 0.0f,
shxy, 1.0f, 0.0f,
shxz, shyz, 1.0f);
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs) {
return scale_shear_mat(1.0f, 1.0f, 1.0f,
shxy, shxz, shyz, cs);
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix::scale_shear_mat
// Access: Public, Static
// Description: Returns a matrix that applies the indicated
// scale and shear.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz,
FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs) {
return scale_shear_mat(FLOATNAME(LVecBase3)(sx, sy, sz),
FLOATNAME(LVecBase3)(shxy, shxz, shyz),
cs);
}
////////////////////////////////////////////////////////////////////

View File

@ -49,6 +49,77 @@ const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_lz_to_ry_mat =
const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_ly_to_rz_mat =
FLOATNAME(LMatrix3)::_flip_z_mat * FLOATNAME(LMatrix3)::_y_to_z_up_mat;
////////////////////////////////////////////////////////////////////
// Function: LMatrix::scale_shear_mat
// Access: Public, Static
// Description: Returns a matrix that applies the indicated
// scale and shear.
////////////////////////////////////////////////////////////////////
FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
scale_shear_mat(const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs) {
if (cs == CS_default) {
cs = default_coordinate_system;
}
// We have to match the placement of the shear components in the
// matrix to the way we extract out the rotation in
// decompose_matrix(). Therefore, the shear is sensitive to the
// coordinate system.
switch (cs) {
case CS_zup_right:
if (temp_hpr_fix) {
return FLOATNAME(LMatrix3)(scale._v.v._0, shear._v.v._0 * scale._v.v._0, 0.0f,
0.0f, scale._v.v._1, 0.0f,
shear._v.v._1 * scale._v.v._2, shear._v.v._2 * scale._v.v._2, scale._v.v._2);
} else {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, 0.0f,
shear._v.v._1 * scale._v.v._2, shear._v.v._2 * scale._v.v._2, scale._v.v._2);
}
case CS_zup_left:
if (temp_hpr_fix) {
return FLOATNAME(LMatrix3)(scale._v.v._0, shear._v.v._0 * scale._v.v._0, 0.0f,
0.0f, scale._v.v._1, 0.0f,
-shear._v.v._1 * scale._v.v._2, -shear._v.v._2 * scale._v.v._2, scale._v.v._2);
} else {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, 0.0f,
-shear._v.v._1 * scale._v.v._2, -shear._v.v._2 * scale._v.v._2, scale._v.v._2);
}
case CS_yup_right:
if (temp_hpr_fix) {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, shear._v.v._1 * scale._v.v._0,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, shear._v.v._2 * scale._v.v._1,
0.0f, 0.0f, scale._v.v._2);
} else {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, shear._v.v._2 * scale._v.v._1,
shear._v.v._1 * scale._v.v._2, 0.0f, scale._v.v._2);
}
case CS_yup_left:
if (temp_hpr_fix) {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, -shear._v.v._1 * scale._v.v._0,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, -shear._v.v._2 * scale._v.v._1,
0.0f, 0.0f, scale._v.v._2);
} else {
return FLOATNAME(LMatrix3)(scale._v.v._0, 0.0f, 0.0f,
shear._v.v._0 * scale._v.v._1, scale._v.v._1, -shear._v.v._2 * scale._v.v._1,
-shear._v.v._1 * scale._v.v._2, 0.0f, scale._v.v._2);
}
}
linmath_cat.error()
<< "Invalid coordinate system value!\n";
return _ident_mat;
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix::convert_mat
// Access: Public, Static

View File

@ -99,9 +99,6 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LMatrix3) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LMatrix3) operator / (FLOATTYPE scalar) const;
// this = scale_mat(scale_vector) * other_mat, efficiently
INLINE_LINMATH void scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix3) &other_mat);
INLINE_LINMATH FLOATNAME(LMatrix3) &operator += (const FLOATNAME(LMatrix3) &other);
INLINE_LINMATH FLOATNAME(LMatrix3) &operator -= (const FLOATNAME(LMatrix3) &other);
@ -158,9 +155,20 @@ PUBLISHED:
scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz);
static INLINE_LINMATH FLOATNAME(LMatrix3)
shear_mat(const FLOATNAME(LVecBase3) &shear);
shear_mat(const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs = CS_default);
static INLINE_LINMATH FLOATNAME(LMatrix3)
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz);
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs = CS_default);
static FLOATNAME(LMatrix3)
scale_shear_mat(const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs = CS_default);
static INLINE_LINMATH FLOATNAME(LMatrix3)
scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz,
FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs = CS_default);
static const FLOATNAME(LMatrix3) &convert_mat(CoordinateSystem from,
CoordinateSystem to);

View File

@ -730,31 +730,6 @@ multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &other2) {
MATRIX4_PRODUCT((*this),other1,other2);
}
// this = scale_mat(scale_vector) * other_mat, efficiently
INLINE_LINMATH void FLOATNAME(LMatrix4)::
scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix4) &other_mat) {
#ifdef _DEBUG
assert(&other_mat != this);
#endif
// optimize for 0.0 or 1.0 factors?
_m.m._00 = other_mat._m.m._00 * scale_vector._v.v._0;
_m.m._01 = other_mat._m.m._01 * scale_vector._v.v._0;
_m.m._02 = other_mat._m.m._02 * scale_vector._v.v._0;
_m.m._03 = other_mat._m.m._03 * scale_vector._v.v._0;
_m.m._10 = other_mat._m.m._10 * scale_vector._v.v._1;
_m.m._11 = other_mat._m.m._11 * scale_vector._v.v._1;
_m.m._12 = other_mat._m.m._12 * scale_vector._v.v._1;
_m.m._13 = other_mat._m.m._13 * scale_vector._v.v._1;
_m.m._20 = other_mat._m.m._20 * scale_vector._v.v._2;
_m.m._21 = other_mat._m.m._21 * scale_vector._v.v._2;
_m.m._22 = other_mat._m.m._22 * scale_vector._v.v._2;
_m.m._23 = other_mat._m.m._23 * scale_vector._v.v._2;
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix4::matrix * scalar
// Access: Public
@ -1359,11 +1334,9 @@ scale_mat(FLOATTYPE scale) {
// shear in each of the three planes.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
shear_mat(const FLOATNAME(LVecBase3) &shear) {
return FLOATNAME(LMatrix4)(1.0f, 0.0f, 0.0f, 0.0f,
shear._v.v._0, 1.0f, 0.0f, 0.0f,
shear._v.v._1, shear._v.v._2, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs) {
return scale_shear_mat(FLOATNAME(LVecBase3)(1.0f, 1.0f, 1.0f),
shear, cs);
}
////////////////////////////////////////////////////////////////////
@ -1373,11 +1346,38 @@ shear_mat(const FLOATNAME(LVecBase3) &shear) {
// shear in each of the three planes.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz) {
return FLOATNAME(LMatrix4)(1.0f, 0.0f, 0.0f, 0.0f,
shxy, 1.0f, 0.0f, 0.0f,
shxz, shyz, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs) {
return scale_shear_mat(1.0f, 1.0f, 1.0f,
shxy, shxz, shyz, cs);
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix::scale_shear_mat
// Access: Public, Static
// Description: Returns a matrix that applies the indicated
// scale and shear.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
scale_shear_mat(const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs) {
return FLOATNAME(LMatrix4)(FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs));
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix::scale_shear_mat
// Access: Public, Static
// Description: Returns a matrix that applies the indicated
// scale and shear.
////////////////////////////////////////////////////////////////////
INLINE_LINMATH FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz,
FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs) {
return scale_shear_mat(FLOATNAME(LVecBase3)(sx, sy, sz),
FLOATNAME(LVecBase3)(shxy, shxz, shyz),
cs);
}
////////////////////////////////////////////////////////////////////

View File

@ -104,9 +104,6 @@ PUBLISHED:
// this = other1 * other2
INLINE_LINMATH void multiply(const FLOATNAME(LMatrix4) &other1, const FLOATNAME(LMatrix4) &other2);
// this = scale_mat(scale_vector) * other_mat, efficiently
INLINE_LINMATH void scale_multiply(const FLOATNAME(LVecBase3) &scale_vector,const FLOATNAME(LMatrix4) &other_mat);
INLINE_LINMATH FLOATNAME(LMatrix4) operator * (const FLOATNAME(LMatrix4) &other) const;
INLINE_LINMATH FLOATNAME(LMatrix4) operator * (FLOATTYPE scalar) const;
@ -153,9 +150,20 @@ PUBLISHED:
scale_mat(FLOATTYPE scale);
static INLINE_LINMATH FLOATNAME(LMatrix4)
shear_mat(const FLOATNAME(LVecBase3) &shear);
shear_mat(const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs = CS_default);
static INLINE_LINMATH FLOATNAME(LMatrix4)
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz);
shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs = CS_default);
static INLINE_LINMATH FLOATNAME(LMatrix4)
scale_shear_mat(const FLOATNAME(LVecBase3) &scale,
const FLOATNAME(LVecBase3) &shear,
CoordinateSystem cs = CS_default);
static INLINE_LINMATH FLOATNAME(LMatrix4)
scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz,
FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz,
CoordinateSystem cs = CS_default);
INLINE_LINMATH static const FLOATNAME(LMatrix4) &y_to_z_up_mat();
INLINE_LINMATH static const FLOATNAME(LMatrix4) &z_to_y_up_mat();

View File

@ -19,9 +19,9 @@
#include "fftCompressor.h"
#include "config_mathutil.h"
#include <datagram.h>
#include <datagramIterator.h>
#include <compose_matrix.h>
#include "datagram.h"
#include "datagramIterator.h"
#include "compose_matrix.h"
#include <math.h>
#ifdef HAVE_FFTW
@ -348,7 +348,8 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
m20, m21, m22;
for (int i = 0; i < length; i++) {
LMatrix3f mat;
compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]);
compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), LVecBase3f(0.0, 0.0, 0.0),
array[i]);
m00.push_back(mat(0, 0));
m01.push_back(mat(0, 1));
m02.push_back(mat(0, 2));
@ -390,7 +391,8 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
for (int i = 0; i < length; i++) {
LMatrix3f mat;
compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]);
compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), LVecBase3f(0.0, 0.0, 0.0),
array[i]);
if (_transpose_quats) {
mat.transpose_in_place();
}
@ -418,31 +420,16 @@ write_hprs(Datagram &datagram, const LVecBase3f *array, int length) {
rot.extract_to_matrix(mat2);
if (!mat.almost_equal(mat2, 0.0001)) {
LVecBase3f hpr1, hpr2;
LVecBase3f scale;
bool d1 = decompose_matrix(mat, scale, hpr1);
bool d2 = decompose_matrix(mat2, scale, hpr2);
LVecBase3f scale, shear;
decompose_matrix(mat, scale, shear, hpr1);
decompose_matrix(mat2, scale, shear, hpr2);
mathutil_cat.warning()
<< "Converted hpr to quaternion incorrectly!\n"
<< " Source hpr: " << array[i];
if (d1) {
mathutil_cat.warning(false)
<< ", or " << hpr1 << "\n";
} else {
mathutil_cat.warning(false)
<< ", incorrectly converted to the non-ortho matrix:\n";
mat2.write(mathutil_cat.warning(false), 4);
}
<< " Source hpr: " << array[i] << ", or " << hpr1 << "\n";
mathutil_cat.warning(false)
<< " Quaternion: " << rot << "\n";
if (d2) {
mathutil_cat.warning(false)
<< " Which represents: hpr " << hpr2 << " scale "
<< scale << "\n";
} else {
mathutil_cat.warning(false)
<< " Which is incorrectly converted to the following non-ortho matrix:\n";
mat2.write(mathutil_cat.warning(false), 4);
}
<< " Quaternion: " << rot << "\n"
<< " Which represents: hpr " << hpr2 << " scale "
<< scale << "\n";
}
}
#endif
@ -628,16 +615,9 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) {
LMatrix3f mat(m00[i], m01[i], m02[i],
m10[i], m11[i], m12[i],
m20[i], m21[i], m22[i]);
LVecBase3f scale, hpr;
bool success = decompose_matrix(mat, scale, hpr);
if (success) {
array.push_back(hpr);
} else {
mathutil_cat.error()
<< "Unable to decompose matrix:\n";
mat.write(mathutil_cat.error(false), 2);
array.push_back(LVecBase3f(0.0, 0.0, 0.0));
}
LVecBase3f scale, shear, hpr;
decompose_matrix(mat, scale, shear, hpr);
array.push_back(hpr);
}
}
@ -694,10 +674,8 @@ read_hprs(DatagramIterator &di, vector_LVecBase3f &array) {
if (_transpose_quats) {
mat.transpose_in_place();
}
LVecBase3f scale, hpr;
bool success = decompose_matrix(mat, scale, hpr);
nassertr(success, false);
LVecBase3f scale, shear, hpr;
decompose_matrix(mat, scale, shear, hpr);
array.push_back(hpr);
}
}

View File

@ -19,12 +19,12 @@
#ifndef FFTCOMPRESSOR_H
#define FFTCOMPRESSOR_H
#include <pandabase.h>
#include "pandabase.h"
#include <pointerToArray.h>
#include <vector_float.h>
#include <vector_double.h>
#include <vector_LVecBase3f.h>
#include "pointerToArray.h"
#include "vector_float.h"
#include "vector_double.h"
#include "vector_LVecBase3f.h"
class Datagram;
class DatagramIterator;

View File

@ -568,7 +568,10 @@ evaluate(float t, LMatrix4f &result, CoordinateSystem cs) const {
return false;
}
compose_matrix(result, LVecBase3f(1.0f, 1.0f, 1.0f), hpr, xyz, cs);
compose_matrix(result,
LVecBase3f(1.0f, 1.0f, 1.0f),
LVecBase3f(0.0f, 0.0f, 0.0f),
hpr, xyz, cs);
return true;
}
@ -935,9 +938,8 @@ determine_hpr(float t, ParametricCurve *xyz_curve, LVecBase3f &hpr) const {
LMatrix3f mat;
look_at(mat, tangent);
LVecBase3f scale;
decompose_matrix(mat, scale, hpr);
return true;
LVecBase3f scale, shear;
return decompose_matrix(mat, scale, shear, hpr);
}
////////////////////////////////////////////////////////////////////

View File

@ -110,12 +110,6 @@ const bool paranoid_compose = config_pgraph.GetBool("paranoid-compose", false);
// by matrix.
const bool compose_componentwise = config_pgraph.GetBool("compose-componentwise", true);
// Set this true to load transforms from bam files as componentwise
// transforms always, even if they were stored as matrix transforms.
// This works around old versions of the egg loader that only stored
// matrix transforms.
const bool bams_componentwise = config_pgraph.GetBool("bams-componentwise", false);
// Set this false to disable TransparencyAttrib::M_dual altogether
// (and use M_alpha in its place).
const bool m_dual = config_pgraph.GetBool("m-dual", true);

View File

@ -33,7 +33,6 @@ extern const bool fake_view_frustum_cull;
extern const bool unambiguous_graph;
extern const bool paranoid_compose;
extern const bool compose_componentwise;
extern const bool bams_componentwise;
extern const bool m_dual;
extern const bool m_dual_opaque;

View File

@ -522,6 +522,32 @@ get_sz() const {
return get_scale()[2];
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_shear
// Access: Published
// Description: Sets the shear component of the transform,
// leaving translation, rotation, and scale untouched.
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
set_shear(float shxy, float shxz, float shyz) {
set_shear(LVecBase3f(shxy, shxz, shyz));
}
INLINE float NodePath::
get_shxy() const {
return get_shear()[0];
}
INLINE float NodePath::
get_shxz() const {
return get_shear()[1];
}
INLINE float NodePath::
get_shyz() const {
return get_shear()[2];
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr
// Access: Published
@ -705,6 +731,38 @@ get_sz(const NodePath &other) const {
return get_scale(other)[2];
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_shear
// Access: Published
// Description: Sets the shear component of the transform,
// relative to the other node.
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
set_shear(const NodePath &other, float shxy, float shxz, float shyz) {
set_shear(other, LPoint3f(shxy, shxz, shyz));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_shear
// Access: Published
// Description: Returns the relative shear of the referenced node
// as seen from the other node.
////////////////////////////////////////////////////////////////////
INLINE float NodePath::
get_shxy(const NodePath &other) const {
return get_shear(other)[0];
}
INLINE float NodePath::
get_shxz(const NodePath &other) const {
return get_shear(other)[1];
}
INLINE float NodePath::
get_shyz(const NodePath &other) const {
return get_shear(other)[2];
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr
// Access: Published

View File

@ -39,7 +39,6 @@
#include "transparencyAttrib.h"
#include "materialPool.h"
#include "look_at.h"
#include "compose_matrix.h"
#include "plist.h"
#include "boundingSphere.h"
#include "geomNode.h"
@ -692,19 +691,6 @@ get_hpr() const {
return transform->get_hpr();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_hpr
// Access: Published
// Description: Retrieves the rotation component of the transform.
////////////////////////////////////////////////////////////////////
LVecBase3f NodePath::
get_hpr(float roll) const {
// This function is deprecated. It used to be a hack to work around
// a problem with decomposing Euler angles, but since we no longer
// depend on decomposing these, we shouldn't need this any more.
return get_hpr();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_quat
// Access: Published
@ -782,6 +768,58 @@ get_scale() const {
return transform->get_scale();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_shear
// Access: Published
// Description: Sets the shear component of the transform,
// leaving translation and rotation untouched.
////////////////////////////////////////////////////////////////////
void NodePath::
set_shear(const LVecBase3f &shear) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
set_transform(transform->set_shear(shear));
}
void NodePath::
set_shxy(float shxy) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
LVecBase3f shear = transform->get_shear();
shear[0] = shxy;
set_transform(transform->set_shear(shear));
}
void NodePath::
set_shxz(float shxz) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
LVecBase3f shear = transform->get_shear();
shear[1] = shxz;
set_transform(transform->set_shear(shear));
}
void NodePath::
set_shyz(float shyz) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
LVecBase3f shear = transform->get_shear();
shear[2] = shyz;
set_transform(transform->set_shear(shear));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_shear
// Access: Published
// Description: Retrieves the shear component of the transform.
////////////////////////////////////////////////////////////////////
LVecBase3f NodePath::
get_shear() const {
nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
CPT(TransformState) transform = get_transform();
return transform->get_shear();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr
// Access: Published
@ -792,8 +830,8 @@ void NodePath::
set_pos_hpr(const LVecBase3f &pos, const LVecBase3f &hpr) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
transform = TransformState::make_pos_hpr_scale
(pos, hpr, transform->get_scale());
transform = TransformState::make_pos_hpr_scale_shear
(pos, hpr, transform->get_scale(), transform->get_shear());
set_transform(transform);
}
@ -807,16 +845,16 @@ void NodePath::
set_hpr_scale(const LVecBase3f &hpr, const LVecBase3f &scale) {
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform();
transform = TransformState::make_pos_hpr_scale
(transform->get_pos(), hpr, scale);
transform = TransformState::make_pos_hpr_scale_shear
(transform->get_pos(), hpr, scale, transform->get_shear());
set_transform(transform);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr_scale
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, and scale components.
// Description: Replaces the translation, rotation, and scale
// components, implicitly setting shear to 0.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
@ -829,8 +867,8 @@ set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_quat_scale
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, and scale components.
// Description: Replaces the translation, rotation, and scale
// components, implicitly setting shear to 0.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
@ -840,6 +878,34 @@ set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
(pos, quat, scale));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr_scale_shear
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, scale, and shear components.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_hpr_scale_shear(const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale, const LVecBase3f &shear) {
nassertv_always(!is_empty());
set_transform(TransformState::make_pos_hpr_scale_shear
(pos, hpr, scale, shear));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_quat_scale_shear
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, scale, and shear components.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_quat_scale_shear(const LVecBase3f &pos, const LQuaternionf &quat,
const LVecBase3f &scale, const LVecBase3f &shear) {
nassertv_always(!is_empty());
set_transform(TransformState::make_pos_quat_scale_shear
(pos, quat, scale, shear));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_mat
// Access: Published
@ -900,14 +966,15 @@ set_pos(const NodePath &other, const LVecBase3f &pos) {
CPT(TransformState) orig_transform = get_transform();
if (orig_transform->has_components()) {
// If we had a componentwise transform before we started, we
// should be careful to preserve the other two components. We
// should be careful to preserve the other three components. We
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_hpr = orig_transform->get_hpr();
const LVecBase3f &orig_scale = orig_transform->get_scale();
const LVecBase3f &orig_shear = orig_transform->get_shear();
set_transform(other, rel_transform->set_pos(pos));
set_pos_hpr_scale(get_transform()->get_pos(), orig_hpr, orig_scale);
set_pos_hpr_scale_shear(get_transform()->get_pos(), orig_hpr, orig_scale, orig_shear);
} else {
// If we didn't have a componentwise transform already, never
@ -967,16 +1034,17 @@ set_hpr(const NodePath &other, const LVecBase3f &hpr) {
CPT(TransformState) orig_transform = get_transform();
if (orig_transform->has_components()) {
// If we had a componentwise transform before we started, we
// should be careful to preserve the other two components. We
// should be careful to preserve the other three components. We
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_pos = orig_transform->get_pos();
const LVecBase3f &orig_scale = orig_transform->get_scale();
const LVecBase3f &orig_shear = orig_transform->get_shear();
set_transform(other, rel_transform->set_hpr(hpr));
const TransformState *new_transform = get_transform();
if (new_transform->has_components()) {
set_pos_hpr_scale(orig_pos, new_transform->get_hpr(), orig_scale);
set_pos_hpr_scale_shear(orig_pos, new_transform->get_hpr(), orig_scale, orig_shear);
}
} else {
@ -1024,22 +1092,6 @@ get_hpr(const NodePath &other) const {
return transform->get_hpr();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_hpr
// Access: Published
// Description: Returns the relative orientation of the bottom node
// as seen from the other node.
////////////////////////////////////////////////////////////////////
LVecBase3f NodePath::
get_hpr(const NodePath &other, float roll) const {
// This is still doing it the dumb way, with a decomposition. This
// function is deprecated anyway.
LMatrix4f mat = get_mat(other);
LVector3f scale, hpr, pos;
decompose_matrix(mat, scale, hpr, pos, roll, CS_default);
return hpr;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_quat
// Access: Published
@ -1054,16 +1106,17 @@ set_quat(const NodePath &other, const LQuaternionf &quat) {
CPT(TransformState) orig_transform = get_transform();
if (orig_transform->has_components()) {
// If we had a componentwise transform before we started, we
// should be careful to preserve the other two components. We
// should be careful to preserve the other three components. We
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_pos = orig_transform->get_pos();
const LVecBase3f &orig_scale = orig_transform->get_scale();
const LVecBase3f &orig_shear = orig_transform->get_shear();
set_transform(other, rel_transform->set_quat(quat));
const TransformState *new_transform = get_transform();
if (new_transform->has_components()) {
set_pos_quat_scale(orig_pos, new_transform->get_quat(), orig_scale);
set_pos_quat_scale_shear(orig_pos, new_transform->get_quat(), orig_scale, orig_shear);
}
} else {
@ -1100,16 +1153,17 @@ set_scale(const NodePath &other, const LVecBase3f &scale) {
CPT(TransformState) orig_transform = get_transform();
if (orig_transform->has_components()) {
// If we had a componentwise transform before we started, we
// should be careful to preserve the other two components. We
// should be careful to preserve the other three components. We
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_pos = orig_transform->get_pos();
const LVecBase3f &orig_hpr = orig_transform->get_hpr();
const LVecBase3f &orig_shear = orig_transform->get_shear();
set_transform(other, rel_transform->set_scale(scale));
const TransformState *new_transform = get_transform();
if (new_transform->has_components()) {
set_pos_hpr_scale(orig_pos, orig_hpr, new_transform->get_scale());
set_pos_hpr_scale_shear(orig_pos, orig_hpr, new_transform->get_scale(), orig_shear);
}
} else {
@ -1156,6 +1210,77 @@ get_scale(const NodePath &other) const {
return transform->get_scale();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_shear
// Access: Published
// Description: Sets the shear component of the transform,
// relative to the other node.
////////////////////////////////////////////////////////////////////
void NodePath::
set_shear(const NodePath &other, const LVecBase3f &shear) {
nassertv_always(!is_empty());
CPT(TransformState) rel_transform = get_transform(other);
CPT(TransformState) orig_transform = get_transform();
if (orig_transform->has_components()) {
// If we had a componentwise transform before we started, we
// should be careful to preserve the other three components. We
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_pos = orig_transform->get_pos();
const LVecBase3f &orig_hpr = orig_transform->get_hpr();
const LVecBase3f &orig_scale = orig_transform->get_scale();
set_transform(other, rel_transform->set_shear(shear));
const TransformState *new_transform = get_transform();
if (new_transform->has_components()) {
set_pos_hpr_scale_shear(orig_pos, orig_hpr, orig_scale, new_transform->get_shear());
}
} else {
// If we didn't have a componentwise transform already, never
// mind.
set_transform(other, rel_transform->set_shear(shear));
}
}
void NodePath::
set_shxy(const NodePath &other, float shxy) {
nassertv_always(!is_empty());
LVecBase3f shear = get_shear(other);
shear[0] = shxy;
set_shear(other, shear);
}
void NodePath::
set_shxz(const NodePath &other, float shxz) {
nassertv_always(!is_empty());
LVecBase3f shear = get_shear(other);
shear[1] = shxz;
set_shear(other, shear);
}
void NodePath::
set_shyz(const NodePath &other, float shyz) {
nassertv_always(!is_empty());
LVecBase3f shear = get_shear(other);
shear[2] = shyz;
set_shear(other, shear);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_shear
// Access: Published
// Description: Returns the relative shear of the bottom node
// as seen from the other node.
////////////////////////////////////////////////////////////////////
LVecBase3f NodePath::
get_shear(const NodePath &other) const {
nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
CPT(TransformState) transform = get_transform(other);
return transform->get_shear();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr
// Access: Published
@ -1175,20 +1300,21 @@ set_pos_hpr(const NodePath &other, const LVecBase3f &pos,
// wouldn't need to do this, except for the possibility of
// numerical error or decompose ambiguity.
const LVecBase3f &orig_scale = orig_transform->get_scale();
const LVecBase3f &orig_shear = orig_transform->get_shear();
set_transform(other, TransformState::make_pos_hpr_scale
(pos, hpr, rel_transform->get_scale()));
set_transform(other, TransformState::make_pos_hpr_scale_shear
(pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
const TransformState *new_transform = get_transform();
if (new_transform->has_components()) {
set_pos_hpr_scale(new_transform->get_pos(), new_transform->get_hpr(),
orig_scale);
set_pos_hpr_scale_shear(new_transform->get_pos(), new_transform->get_hpr(),
orig_scale, orig_shear);
}
} else {
// If we didn't have a componentwise transform already, never
// mind.
set_transform(other, TransformState::make_pos_hpr_scale
(pos, hpr, rel_transform->get_scale()));
set_transform(other, TransformState::make_pos_hpr_scale_shear
(pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
}
}
@ -1208,8 +1334,8 @@ set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &sc
// few thousandths.
nassertv_always(!is_empty());
CPT(TransformState) transform = get_transform(other);
transform = TransformState::make_pos_hpr_scale
(transform->get_pos(), hpr, scale);
transform = TransformState::make_pos_hpr_scale_shear
(transform->get_pos(), hpr, scale, transform->get_shear());
set_transform(other, transform);
}
@ -1218,7 +1344,7 @@ set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &sc
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, and scale components, relative
// to the other node.
// to the other node, implicitly setting shear to 0.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_hpr_scale(const NodePath &other,
@ -1234,7 +1360,7 @@ set_pos_hpr_scale(const NodePath &other,
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, and scale components, relative
// to the other node.
// to the other node, implicitly setting shear to 0.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_quat_scale(const NodePath &other,
@ -1245,6 +1371,38 @@ set_pos_quat_scale(const NodePath &other,
(pos, quat, scale));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_hpr_scale_shear
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, scale, and shear components,
// relative to the other node.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_hpr_scale_shear(const NodePath &other,
const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale, const LVecBase3f &shear) {
nassertv_always(!is_empty());
set_transform(other, TransformState::make_pos_hpr_scale_shear
(pos, hpr, scale, shear));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_pos_quat_scale_shear
// Access: Published
// Description: Completely replaces the transform with new
// translation, rotation, scale, and shear components,
// relative to the other node.
////////////////////////////////////////////////////////////////////
void NodePath::
set_pos_quat_scale_shear(const NodePath &other,
const LVecBase3f &pos, const LQuaternionf &quat,
const LVecBase3f &scale, const LVecBase3f &shear) {
nassertv_always(!is_empty());
set_transform(other, TransformState::make_pos_quat_scale_shear
(pos, quat, scale, shear));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_mat
// Access: Published

View File

@ -250,7 +250,6 @@ PUBLISHED:
void set_p(float p);
void set_r(float r);
LVecBase3f get_hpr() const;
LVecBase3f get_hpr(float roll) const;
INLINE float get_h() const;
INLINE float get_p() const;
INLINE float get_r() const;
@ -269,6 +268,16 @@ PUBLISHED:
INLINE float get_sy() const;
INLINE float get_sz() const;
INLINE void set_shear(float shxy, float shxz, float shyz);
void set_shear(const LVecBase3f &shear);
void set_shxy(float shxy);
void set_shxz(float shxz);
void set_shyz(float shyz);
LVecBase3f get_shear() const;
INLINE float get_shxy() const;
INLINE float get_shxz() const;
INLINE float get_shyz() const;
INLINE void set_pos_hpr(float x, float y, float z,
float h, float p, float r);
void set_pos_hpr(const LVecBase3f &pos,
@ -287,6 +296,14 @@ PUBLISHED:
void set_pos_quat_scale(const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale);
void set_pos_hpr_scale_shear(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale,
const LVecBase3f &shear);
void set_pos_quat_scale_shear(const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale,
const LVecBase3f &shear);
void set_mat(const LMatrix4f &mat);
INLINE void clear_mat();
@ -317,7 +334,6 @@ PUBLISHED:
void set_p(const NodePath &other, float p);
void set_r(const NodePath &other, float r);
LVecBase3f get_hpr(const NodePath &other) const;
LVecBase3f get_hpr(const NodePath &other, float roll) const;
INLINE float get_h(const NodePath &other) const;
INLINE float get_p(const NodePath &other) const;
INLINE float get_r(const NodePath &other) const;
@ -335,6 +351,16 @@ PUBLISHED:
INLINE float get_sy(const NodePath &other) const;
INLINE float get_sz(const NodePath &other) const;
INLINE void set_shear(const NodePath &other, float shxy, float shxz, float shyz);
void set_shear(const NodePath &other, const LVecBase3f &shear);
void set_shxy(const NodePath &other, float shxy);
void set_shxz(const NodePath &other, float shxz);
void set_shyz(const NodePath &other, float shyz);
LVecBase3f get_shear(const NodePath &other) const;
INLINE float get_shxy(const NodePath &other) const;
INLINE float get_shxz(const NodePath &other) const;
INLINE float get_shyz(const NodePath &other) const;
INLINE void set_pos_hpr(const NodePath &other,
float x, float y, float z,
float h, float p, float r);
@ -359,6 +385,16 @@ PUBLISHED:
const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale);
void set_pos_hpr_scale_shear(const NodePath &other,
const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale,
const LVecBase3f &shear);
void set_pos_quat_scale_shear(const NodePath &other,
const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale,
const LVecBase3f &shear);
const LMatrix4f &get_mat(const NodePath &other) const;
void set_mat(const NodePath &other, const LMatrix4f &mat);

View File

@ -114,6 +114,44 @@ make_scale(const LVecBase3f &scale) {
scale);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::make_shear
// Access: Published, Static
// Description: Makes a new TransformState with the specified
// components.
////////////////////////////////////////////////////////////////////
INLINE CPT(TransformState) TransformState::
make_shear(const LVecBase3f &shear) {
return make_pos_hpr_scale_shear(LVecBase3f(0.0f, 0.0f, 0.0f),
LVecBase3f(0.0f, 0.0f, 0.0f),
LVecBase3f(1.0f, 1.0f, 1.0f),
shear);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::make_pos_hpr_scale
// Access: Published, Static
// Description: Makes a new TransformState with the specified
// components.
////////////////////////////////////////////////////////////////////
INLINE CPT(TransformState) TransformState::
make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale) {
return make_pos_hpr_scale_shear(pos, hpr, scale, LVecBase3f::zero());
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::make_pos_quat_scale
// Access: Published, Static
// Description: Makes a new TransformState with the specified
// components.
////////////////////////////////////////////////////////////////////
INLINE CPT(TransformState) TransformState::
make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
const LVecBase3f &scale) {
return make_pos_quat_scale_shear(pos, quat, scale, LVecBase3f::zero());
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::is_identity
// Access: Published
@ -284,6 +322,31 @@ has_uniform_scale() const {
return (_flags & F_uniform_scale) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_shear
// Access: Published
// Description: Returns true if the transform's shear component
// can be extracted out separately. This is generally
// true only when has_components() is true.
////////////////////////////////////////////////////////////////////
INLINE bool TransformState::
has_shear() const {
return has_components();
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_nonzero_shear
// Access: Published
// Description: Returns true if the shear component is non-zero,
// false if it is zero or if the matrix cannot be
// decomposed.
////////////////////////////////////////////////////////////////////
INLINE bool TransformState::
has_nonzero_shear() const {
check_components();
return (_flags & F_has_nonzero_shear) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_mat
// Access: Published
@ -368,6 +431,20 @@ get_uniform_scale() const {
return _scale[0];
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_shear
// Access: Published
// Description: Returns the shear component of the transform. It is
// an error to call this if has_components() returned
// false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &TransformState::
get_shear() const {
check_components();
nassertr(!is_invalid(), _shear);
return _shear;
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_mat
// Access: Published
@ -458,7 +535,8 @@ check_mat() const {
// Access: Private
// Description: Should be called immediately after _scale (and
// F_has_components) is set, this checks for a uniform
// scale and sets the bit appropriately.
// scale (as well as a non-zero shear) and sets the bit
// appropriately.
////////////////////////////////////////////////////////////////////
INLINE void TransformState::
check_uniform_scale() {
@ -466,6 +544,9 @@ check_uniform_scale() {
IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
_flags |= F_uniform_scale;
}
if (!_shear.almost_equal(LVecBase3f::zero())) {
_flags |= F_has_nonzero_shear;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -244,6 +244,11 @@ operator < (const TransformState &other) const {
}
c = _scale.compare_to(other._scale);
if (c != 0) {
return c < 0;
}
c = _shear.compare_to(other._shear);
return c < 0;
}
@ -294,18 +299,19 @@ make_invalid() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::make_pos_hpr_scale
// Function: TransformState::make_pos_hpr_scale_shear
// Access: Published, Static
// Description: Makes a new TransformState with the specified
// components.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale) {
make_pos_hpr_scale_shear(const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale, const LVecBase3f &shear) {
// Make a special-case check for the identity transform.
if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
hpr == LVecBase3f(0.0f, 0.0f, 0.0f) &&
scale == LVecBase3f(1.0f, 1.0f, 1.0f)) {
scale == LVecBase3f(1.0f, 1.0f, 1.0f) &&
shear == LVecBase3f(0.0f, 0.0f, 0.0f)) {
return make_identity();
}
@ -313,24 +319,26 @@ make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
state->_pos = pos;
state->_hpr = hpr;
state->_scale = scale;
state->_shear = shear;
state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components;
state->check_uniform_scale();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::make_pos_quat_scale
// Function: TransformState::make_pos_quat_scale_shear
// Access: Published, Static
// Description: Makes a new TransformState with the specified
// components.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
const LVecBase3f &scale) {
make_pos_quat_scale_shear(const LVecBase3f &pos, const LQuaternionf &quat,
const LVecBase3f &scale, const LVecBase3f &shear) {
// Make a special-case check for the identity transform.
if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
quat == LQuaternionf::ident_quat() &&
scale == LVecBase3f(1.0f, 1.0f, 1.0f)) {
scale == LVecBase3f(1.0f, 1.0f, 1.0f) &&
shear == LVecBase3f(0.0f, 0.0f, 0.0f)) {
return make_identity();
}
@ -338,6 +346,7 @@ make_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
state->_pos = pos;
state->_quat = quat;
state->_scale = scale;
state->_shear = shear;
state->_flags = F_components_given | F_quat_given | F_components_known | F_quat_known | F_has_components;
state->check_uniform_scale();
return return_new(state);
@ -376,9 +385,9 @@ set_pos(const LVecBase3f &pos) const {
// If we started with a componentwise transform, we keep it that
// way.
if (quat_given()) {
return make_pos_quat_scale(pos, get_quat(), get_scale());
return make_pos_quat_scale_shear(pos, get_quat(), get_scale(), get_shear());
} else {
return make_pos_hpr_scale(pos, get_hpr(), get_scale());
return make_pos_hpr_scale_shear(pos, get_hpr(), get_scale(), get_shear());
}
} else {
@ -400,7 +409,7 @@ CPT(TransformState) TransformState::
set_hpr(const LVecBase3f &hpr) const {
nassertr(!is_invalid(), this);
// nassertr(has_components(), this);
return make_pos_hpr_scale(get_pos(), hpr, get_scale());
return make_pos_hpr_scale_shear(get_pos(), hpr, get_scale(), get_shear());
}
////////////////////////////////////////////////////////////////////
@ -414,7 +423,7 @@ CPT(TransformState) TransformState::
set_quat(const LQuaternionf &quat) const {
nassertr(!is_invalid(), this);
// nassertr(has_components(), this);
return make_pos_quat_scale(get_pos(), quat, get_scale());
return make_pos_quat_scale_shear(get_pos(), quat, get_scale(), get_shear());
}
////////////////////////////////////////////////////////////////////
@ -429,9 +438,27 @@ set_scale(const LVecBase3f &scale) const {
nassertr(!is_invalid(), this);
// nassertr(has_components(), this);
if (quat_given()) {
return make_pos_quat_scale(get_pos(), get_quat(), scale);
return make_pos_quat_scale_shear(get_pos(), get_quat(), scale, get_shear());
} else {
return make_pos_hpr_scale(get_pos(), get_hpr(), scale);
return make_pos_hpr_scale_shear(get_pos(), get_hpr(), scale, get_shear());
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::set_shear
// Access: Published
// Description: Returns a new TransformState object that represents the
// original TransformState with its shear component
// replaced with the indicated value, if possible.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
set_shear(const LVecBase3f &shear) const {
nassertr(!is_invalid(), this);
// nassertr(has_components(), this);
if (quat_given()) {
return make_pos_quat_scale_shear(get_pos(), get_quat(), get_scale(), shear);
} else {
return make_pos_hpr_scale_shear(get_pos(), get_hpr(), get_scale(), shear);
}
}
@ -611,10 +638,10 @@ output(ostream &out) const {
out << "m";
} else if (output_hpr && quat_given()) {
// A leading "q" indicates that the pos and scale are exactly as
// specified, but the rotation was described as a quaternion,
// and we are decomposing that to hpr for the benefit of the
// user.
// A leading "q" indicates that the pos, scale, and shear are
// exactly as specified, but the rotation was described as a
// quaternion, and we are decomposing that to hpr for the
// benefit of the user.
out << "q";
}
@ -636,6 +663,10 @@ output(ostream &out) const {
lead = ' ';
}
}
if (has_nonzero_shear()) {
out << lead << "shear " << get_shear();
lead = ' ';
}
if (lead == '(') {
out << "(almost identity)";
} else {
@ -879,6 +910,7 @@ do_compose(const TransformState *other) const {
if (compose_componentwise &&
has_uniform_scale() &&
!has_nonzero_shear() && !other->has_nonzero_shear() &&
((components_given() && other->has_components()) ||
(other->components_given() && has_components()))) {
// We will do this operation componentwise if *either* transform
@ -932,6 +964,7 @@ do_invert_compose(const TransformState *other) const {
if (compose_componentwise &&
has_uniform_scale() &&
!has_nonzero_shear() && !other->has_nonzero_shear() &&
((components_given() && other->has_components()) ||
(other->components_given() && has_components()))) {
// We will do this operation componentwise if *either* transform
@ -1040,6 +1073,7 @@ calc_components() {
nassertv((_flags & F_is_invalid) == 0);
if ((_flags & F_is_identity) != 0) {
_scale.set(1.0f, 1.0f, 1.0f);
_shear.set(0.0f, 0.0f, 0.0f);
_hpr.set(0.0f, 0.0f, 0.0f);
_quat = LQuaternionf::ident_quat();
_pos.set(0.0f, 0.0f, 0.0f);
@ -1051,7 +1085,7 @@ calc_components() {
nassertv((_flags & F_mat_known) != 0);
const LMatrix4f &mat = get_mat();
bool possible = decompose_matrix(mat, _scale, _hpr, _pos);
bool possible = decompose_matrix(mat, _scale, _shear, _hpr, _pos);
if (!possible) {
// Some matrices can't be decomposed into scale, hpr, pos. In
// this case, we now know that we cannot compute the components;
@ -1121,7 +1155,7 @@ calc_mat() {
// If we don't have a matrix and we're not identity, the only
// other explanation is that we were constructed via components.
nassertv((_flags & F_components_known) != 0);
compose_matrix(_mat, _scale, get_hpr(), _pos);
compose_matrix(_mat, _scale, _shear, get_hpr(), _pos);
}
_flags |= F_mat_known;
}
@ -1175,6 +1209,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
get_hpr().write_datagram(dg);
}
_scale.write_datagram(dg);
_shear.write_datagram(dg);
} else {
// A general matrix.
@ -1283,19 +1318,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
_flags |= (F_hpr_given | F_hpr_known);
}
_scale.read_datagram(scan);
if (manager->get_file_minor_ver() >= 6) {
_shear.read_datagram(scan);
} else {
_shear.set(0.0f, 0.0f, 0.0f);
}
check_uniform_scale();
}
if ((_flags & F_mat_known) != 0) {
// General matrix.
_mat.read_datagram(scan);
if (bams_componentwise) {
// Decompose the matrix if we can, and store it componentwise.
if (has_components()) {
_flags |= F_components_given | F_hpr_given;
}
}
}
}

View File

@ -76,12 +76,21 @@ PUBLISHED:
const LVecBase3f &hpr);
INLINE static CPT(TransformState) make_scale(float scale);
INLINE static CPT(TransformState) make_scale(const LVecBase3f &scale);
static CPT(TransformState) make_pos_hpr_scale(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale);
static CPT(TransformState) make_pos_quat_scale(const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale);
INLINE static CPT(TransformState) make_shear(const LVecBase3f &scale);
INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale);
INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale);
static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale,
const LVecBase3f &shear);
static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3f &pos,
const LQuaternionf &quat,
const LVecBase3f &scale,
const LVecBase3f &shear);
static CPT(TransformState) make_mat(const LMatrix4f &mat);
INLINE bool is_identity() const;
@ -96,18 +105,22 @@ PUBLISHED:
INLINE bool has_quat() const;
INLINE bool has_scale() const;
INLINE bool has_uniform_scale() const;
INLINE bool has_shear() const;
INLINE bool has_nonzero_shear() const;
INLINE bool has_mat() const;
INLINE const LVecBase3f &get_pos() const;
INLINE const LVecBase3f &get_hpr() const;
INLINE const LQuaternionf &get_quat() const;
INLINE const LVecBase3f &get_scale() const;
INLINE float get_uniform_scale() const;
INLINE const LVecBase3f &get_shear() const;
INLINE const LMatrix4f &get_mat() const;
CPT(TransformState) set_pos(const LVecBase3f &pos) const;
CPT(TransformState) set_hpr(const LVecBase3f &hpr) const;
CPT(TransformState) set_quat(const LQuaternionf &quat) const;
CPT(TransformState) set_scale(const LVecBase3f &scale) const;
CPT(TransformState) set_shear(const LVecBase3f &shear) const;
CPT(TransformState) compose(const TransformState *other) const;
CPT(TransformState) invert_compose(const TransformState *other) const;
@ -175,22 +188,23 @@ private:
INLINE bool is_destructing() const;
enum Flags {
F_is_identity = 0x0001,
F_is_singular = 0x0002,
F_singular_known = 0x0004, // set if we know F_is_singular
F_components_given = 0x0008,
F_components_known = 0x0010, // set if we know F_has_components
F_has_components = 0x0020,
F_mat_known = 0x0040, // set if _mat is defined
F_is_invalid = 0x0080,
F_quat_given = 0x0100,
F_quat_known = 0x0200, // set if _quat is defined
F_hpr_given = 0x0400,
F_hpr_known = 0x0800, // set if _hpr is defined
F_uniform_scale = 0x1000,
F_is_destructing = 0x8000,
F_is_identity = 0x0001,
F_is_singular = 0x0002,
F_singular_known = 0x0004, // set if we know F_is_singular
F_components_given = 0x0008,
F_components_known = 0x0010, // set if we know F_has_components
F_has_components = 0x0020,
F_mat_known = 0x0040, // set if _mat is defined
F_is_invalid = 0x0080,
F_quat_given = 0x0100,
F_quat_known = 0x0200, // set if _quat is defined
F_hpr_given = 0x0400,
F_hpr_known = 0x0800, // set if _hpr is defined
F_uniform_scale = 0x1000,
F_has_nonzero_shear = 0x2000,
F_is_destructing = 0x8000,
};
LVecBase3f _pos, _hpr, _scale;
LVecBase3f _pos, _hpr, _scale, _shear;
LQuaternionf _quat;
LMatrix4f _mat;
LMatrix4f *_inv_mat;

View File

@ -34,12 +34,13 @@ static const unsigned short _bam_major_ver = 4;
// Bumped to major version 3 on 12/8/00 to change float64's to float32's.
// Bumped to major version 4 on 4/10/02 to store new scene graph.
static const unsigned short _bam_minor_ver = 5;
static const unsigned short _bam_minor_ver = 6;
// Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
// Bumped to minor version 2 on 4/12/03 to add num_components to texture.
// Bumped to minor version 3 on 4/15/03 to add ImageBuffer::_alpha_file_channel
// Bumped to minor version 4 on 6/12/03 to add PandaNode::set_tag().
// Bumped to minor version 5 on 7/09/03 to add rawdata mode to texture
// Bumped to minor version 5 on 7/09/03 to add rawdata mode to texture.
// Bumped to minor version 6 on 7/22/03 to add shear to scene graph and animation data.
#endif

View File

@ -26,7 +26,6 @@
#include <renderBuffer.h>
#include <perspectiveProjection.h>
#include <look_at.h>
#include <compose_matrix.h>
#include <get_rel_pos.h>
#include <lightTransition.h>
#include <depthTestTransition.h>

View File

@ -27,7 +27,6 @@
#include <renderBuffer.h>
#include <perspectiveLens.h>
#include <look_at.h>
#include <compose_matrix.h>
#include <cullFaceTransition.h>
#include <colorBlendTransition.h>
#include <transformTransition.h>

View File

@ -233,11 +233,12 @@ write(ostream &out, int indent_level) const {
<< "draw order is " << _draw_order << ", "
<< _draw_order + 1 << ", " << _draw_order + 2 << "\n";
LVecBase3f scale, hpr, trans;
if (decompose_matrix(_transform, scale, hpr, trans, _coordinate_system)) {
LVecBase3f scale, shear, hpr, trans;
if (decompose_matrix(_transform, scale, shear, hpr, trans, _coordinate_system)) {
indent(out, indent_level + 2)
<< "transform is:\n"
<< " scale: " << scale << "\n"
<< " shear: " << shear << "\n"
<< " hpr: " << hpr << "\n"
<< " trans: " << hpr << "\n";
} else {

View File

@ -190,8 +190,8 @@ set_force_roll(float) {
////////////////////////////////////////////////////////////////////
void DriveInterface::
set_mat(const LMatrix4f &mat) {
LVecBase3f scale;
decompose_matrix(mat, scale, _hpr, _xyz);
LVecBase3f scale, shear;
decompose_matrix(mat, scale, shear, _hpr, _xyz);
}
////////////////////////////////////////////////////////////////////
@ -201,7 +201,10 @@ set_mat(const LMatrix4f &mat) {
////////////////////////////////////////////////////////////////////
const LMatrix4f &DriveInterface::
get_mat() {
compose_matrix(_mat, LVecBase3f(1.0f, 1.0f, 1.0f), _hpr, _xyz);
compose_matrix(_mat,
LVecBase3f(1.0f, 1.0f, 1.0f),
LVecBase3f(0.0f, 0.0f, 0.0f),
_hpr, _xyz);
return _mat;
}

View File

@ -180,29 +180,29 @@ set_z(float z) {
////////////////////////////////////////////////////////////////////
LVecBase3f Trackball::
get_hpr() const {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
return hpr;
}
float Trackball::
get_h() const {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
return hpr[0];
}
float Trackball::
get_p() const {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
return hpr[1];
}
float Trackball::
get_r() const {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
return hpr[2];
}
@ -214,45 +214,45 @@ get_r() const {
////////////////////////////////////////////////////////////////////
void Trackball::
set_hpr(const LVecBase3f &hpr) {
LVecBase3f scale, old_hpr, translate;
decompose_matrix(_rotation, scale, old_hpr, translate);
compose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, old_hpr, translate;
decompose_matrix(_rotation, scale, shear, old_hpr, translate);
compose_matrix(_rotation, scale, shear, hpr, translate);
recompute();
}
void Trackball::
set_hpr(float h, float p, float r) {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
hpr.set(h, p, r);
compose_matrix(_rotation, scale, hpr, translate);
compose_matrix(_rotation, scale, shear, hpr, translate);
recompute();
}
void Trackball::
set_h(float h) {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
hpr[0] = h;
compose_matrix(_rotation, scale, hpr, translate);
compose_matrix(_rotation, scale, shear, hpr, translate);
recompute();
}
void Trackball::
set_p(float p) {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
hpr[1] = p;
compose_matrix(_rotation, scale, hpr, translate);
compose_matrix(_rotation, scale, shear, hpr, translate);
recompute();
}
void Trackball::
set_r(float r) {
LVecBase3f scale, hpr, translate;
decompose_matrix(_rotation, scale, hpr, translate);
LVecBase3f scale, shear, hpr, translate;
decompose_matrix(_rotation, scale, shear, hpr, translate);
hpr[2] = r;
compose_matrix(_rotation, scale, hpr, translate);
compose_matrix(_rotation, scale, shear, hpr, translate);
recompute();
}

View File

@ -90,9 +90,9 @@ EggOptchar() {
&EggOptchar::dispatch_vector_string_comma, NULL, &_expose_components);
add_option
("zero", "joint[,hprxyzijk]", 0,
("zero", "joint[,hprxyzijkabc]", 0,
"Zeroes out the animation channels for the named joint. If "
"a subset of the component letters hprxyzijk is included, the "
"a subset of the component letters hprxyzijkabc is included, the "
"operation is restricted to just those components; otherwise the "
"entire transform is cleared.",
&EggOptchar::dispatch_name_components, NULL, &_zero_channels);
@ -272,14 +272,14 @@ dispatch_name_components(const string &opt, const string &arg, void *var) {
}
if (sp._b.empty()) {
sp._b = matrix_components;
sp._b = matrix_component_letters;
} else {
for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) {
if (strchr(matrix_components, *si) == NULL) {
if (strchr(matrix_component_letters, *si) == NULL) {
nout << "Not a standard matrix component: \"" << *si << "\"\n"
<< "-" << opt << " requires a joint name followed by a set "
<< "of component names. The standard component names are \""
<< matrix_components << "\".\n";
<< matrix_component_letters << "\".\n";
return false;
}
}

View File

@ -211,6 +211,10 @@ do_reparent() {
}
}
// Report the set of joints that failed. It really shouldn't be
// possible for any joints to fail, so if you see anything reported
// here, something went wrong at a fundamental level. Perhaps a
// problem with decompose_matrix().
InvalidSet::const_iterator si;
for (si = invalid_set.begin(); si != invalid_set.end(); ++si) {
EggJointData *joint_data = (*si);
@ -225,7 +229,7 @@ do_reparent() {
} else {
nout << joint_data->get_parent()->get_name();
}
nout << " results in a skew transform.\n";
nout << " results in an invalid transform.\n";
}
}

View File

@ -198,16 +198,18 @@ do_rebuild() {
return false;
}
bool all_ok = true;
_xform->clear_data();
RebuildFrames::const_iterator fi;
for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) {
if (!_xform->add_data(*fi)) {
return false;
all_ok = false;
}
}
_rebuild_frames.clear();
return true;
return all_ok;
}
////////////////////////////////////////////////////////////////////

View File

@ -455,7 +455,7 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
if (!anim->add_data(tgroup->get_transform())) {
mayaegg_cat.error()
<< "Shear transform on " << node_desc->get_name()
<< "Invalid transform on " << node_desc->get_name()
<< " frame " << frame.value() << ".\n";
}
}