mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 17:35:34 -04:00
Correct scaling of normals during flatten operations
This commit is contained in:
parent
c85a92d378
commit
bac400543a
@ -118,7 +118,7 @@ munge_format_impl(const GeomVertexFormat *orig,
|
|||||||
|
|
||||||
if (normal_type != (const GeomVertexColumn *)NULL) {
|
if (normal_type != (const GeomVertexColumn *)NULL) {
|
||||||
new_array_format->add_column
|
new_array_format->add_column
|
||||||
(InternalName::get_normal(), 3, NT_float32, C_vector);
|
(InternalName::get_normal(), 3, NT_float32, C_normal);
|
||||||
new_format->remove_column(normal_type->get_name());
|
new_format->remove_column(normal_type->get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
|
|||||||
|
|
||||||
if (normal_type != (const GeomVertexColumn *)NULL) {
|
if (normal_type != (const GeomVertexColumn *)NULL) {
|
||||||
new_array_format->add_column
|
new_array_format->add_column
|
||||||
(InternalName::get_normal(), 3, NT_float32, C_vector);
|
(InternalName::get_normal(), 3, NT_float32, C_normal);
|
||||||
new_format->remove_column(normal_type->get_name());
|
new_format->remove_column(normal_type->get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2240,7 +2240,7 @@ make_vertex_data(const EggRenderState *render_state,
|
|||||||
if (vertex_pool->has_normals()) {
|
if (vertex_pool->has_normals()) {
|
||||||
array_format->add_column
|
array_format->add_column
|
||||||
(InternalName::get_normal(), 3,
|
(InternalName::get_normal(), 3,
|
||||||
Geom::NT_stdfloat, Geom::C_vector);
|
Geom::NT_stdfloat, Geom::C_normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignore_color) {
|
if (!ignore_color) {
|
||||||
|
@ -139,6 +139,9 @@ operator << (ostream &out, GeomEnums::Contents contents) {
|
|||||||
|
|
||||||
case GeomEnums::C_matrix:
|
case GeomEnums::C_matrix:
|
||||||
return out << "matrix";
|
return out << "matrix";
|
||||||
|
|
||||||
|
case GeomEnums::C_normal:
|
||||||
|
return out << "normal";
|
||||||
}
|
}
|
||||||
|
|
||||||
return out << "**invalid contents (" << (int)contents << ")**";
|
return out << "**invalid contents (" << (int)contents << ")**";
|
||||||
|
@ -192,7 +192,7 @@ PUBLISHED:
|
|||||||
C_other, // Arbitrary meaning, leave it alone
|
C_other, // Arbitrary meaning, leave it alone
|
||||||
C_point, // A point in 3-space or 4-space
|
C_point, // A point in 3-space or 4-space
|
||||||
C_clip_point, // A point pre-transformed into clip coordinates
|
C_clip_point, // A point pre-transformed into clip coordinates
|
||||||
C_vector, // A surface normal, tangent, or binormal
|
C_vector, // A surface tangent or binormal (see C_normal for normals)
|
||||||
C_texcoord, // A texture coordinate
|
C_texcoord, // A texture coordinate
|
||||||
C_color, // 3- or 4-component color, ordered R, G, B, [A]
|
C_color, // 3- or 4-component color, ordered R, G, B, [A]
|
||||||
C_index, // An index value into some other table
|
C_index, // An index value into some other table
|
||||||
@ -201,6 +201,10 @@ PUBLISHED:
|
|||||||
// A transformation matrix. This is typically three or four
|
// A transformation matrix. This is typically three or four
|
||||||
// columns, but we pretend it's only one for convenience.
|
// columns, but we pretend it's only one for convenience.
|
||||||
C_matrix,
|
C_matrix,
|
||||||
|
|
||||||
|
// A special version of C_vector that should be used for normal
|
||||||
|
// vectors, which are scaled differently from other vectors.
|
||||||
|
C_normal,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The type of animation data that is represented by a particular
|
// The type of animation data that is represented by a particular
|
||||||
|
@ -394,8 +394,11 @@ align_columns_for_animation() {
|
|||||||
Columns::const_iterator ci;
|
Columns::const_iterator ci;
|
||||||
for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
|
for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
|
||||||
GeomVertexColumn *column = (*ci);
|
GeomVertexColumn *column = (*ci);
|
||||||
if ((column->get_contents() == C_point || column->get_contents() == C_vector) &&
|
if ((column->get_contents() == C_point ||
|
||||||
(column->get_numeric_type() == NT_float32 || column->get_numeric_type() == NT_float64) &&
|
column->get_contents() == C_vector ||
|
||||||
|
column->get_contents() == C_normal) &&
|
||||||
|
(column->get_numeric_type() == NT_float32 ||
|
||||||
|
column->get_numeric_type() == NT_float64) &&
|
||||||
column->get_num_components() >= 3) {
|
column->get_num_components() >= 3) {
|
||||||
add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
|
add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
|
||||||
} else {
|
} else {
|
||||||
|
@ -340,6 +340,11 @@ make_packer() const {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return new Packer_color;
|
return new Packer_color;
|
||||||
|
case C_normal:
|
||||||
|
if (get_num_values() != 3) {
|
||||||
|
gobj_cat.error()
|
||||||
|
<< "GeomVertexColumn with contents C_normal must have 3 components!\n";
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// Otherwise, we just read it as a generic value.
|
// Otherwise, we just read it as a generic value.
|
||||||
switch (get_numeric_type()) {
|
switch (get_numeric_type()) {
|
||||||
|
@ -1915,10 +1915,37 @@ do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &da
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GeomVertexData::
|
void GeomVertexData::
|
||||||
do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
||||||
const LMatrix4 &mat, int begin_row, int end_row) {
|
const LMatrix4 &mat, int begin_row, int end_row) {
|
||||||
const GeomVertexColumn *data_column = data.get_column();
|
const GeomVertexColumn *data_column = data.get_column();
|
||||||
int num_values = data_column->get_num_values();
|
int num_values = data_column->get_num_values();
|
||||||
|
|
||||||
|
LMatrix4 xform;
|
||||||
|
bool normalize = false;
|
||||||
|
if (data_column->get_contents() == C_normal) {
|
||||||
|
// This is to preserve perpendicularity to the surface.
|
||||||
|
LVecBase3 scale, shear, hpr;
|
||||||
|
if (decompose_matrix(mat.get_upper_3(), scale, shear, hpr) &&
|
||||||
|
IS_NEARLY_EQUAL(scale[0], scale[1]) &&
|
||||||
|
IS_NEARLY_EQUAL(scale[0], scale[2])) {
|
||||||
|
if (scale[0] == 1) {
|
||||||
|
// No scale to worry about.
|
||||||
|
xform = mat;
|
||||||
|
} else {
|
||||||
|
// Simply take the uniform scale out of the transformation.
|
||||||
|
// Not sure if it might be better to just normalize?
|
||||||
|
compose_matrix(xform, LVecBase3(1, 1, 1), shear, hpr, LVecBase3::zero());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is a non-uniform scale, so we need to do all this to
|
||||||
|
// preserve orthogonality to the surface.
|
||||||
|
xform.invert_from(mat);
|
||||||
|
xform.transpose_in_place();
|
||||||
|
normalize = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xform = mat;
|
||||||
|
}
|
||||||
|
|
||||||
if ((num_values == 3 || num_values == 4) &&
|
if ((num_values == 3 || num_values == 4) &&
|
||||||
data_column->get_numeric_type() == NT_float32) {
|
data_column->get_numeric_type() == NT_float32) {
|
||||||
// The table of vectors is a table of LVector3f's or LVector4f's.
|
// The table of vectors is a table of LVector3f's or LVector4f's.
|
||||||
@ -1929,9 +1956,11 @@ do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &d
|
|||||||
size_t num_rows = end_row - begin_row;
|
size_t num_rows = end_row - begin_row;
|
||||||
unsigned char *datat = data_handle->get_write_pointer();
|
unsigned char *datat = data_handle->get_write_pointer();
|
||||||
datat += data_column->get_start() + begin_row * stride;
|
datat += data_column->get_start() + begin_row * stride;
|
||||||
LMatrix4f matf = LCAST(float, mat);
|
LMatrix4f matf = LCAST(float, xform);
|
||||||
|
|
||||||
if (num_values == 3) {
|
if (normalize) {
|
||||||
|
table_xform_normal3f(datat, num_rows, stride, matf);
|
||||||
|
} else if (num_values == 3) {
|
||||||
table_xform_vector3f(datat, num_rows, stride, matf);
|
table_xform_vector3f(datat, num_rows, stride, matf);
|
||||||
} else {
|
} else {
|
||||||
table_xform_vecbase4f(datat, num_rows, stride, matf);
|
table_xform_vecbase4f(datat, num_rows, stride, matf);
|
||||||
@ -1939,11 +1968,20 @@ do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &d
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Use the GeomVertexRewriter to transform the vectors.
|
// Use the GeomVertexRewriter to transform the vectors.
|
||||||
|
|
||||||
data.set_row_unsafe(begin_row);
|
data.set_row_unsafe(begin_row);
|
||||||
for (int j = begin_row; j < end_row; ++j) {
|
|
||||||
LVector3 vertex = data.get_data3();
|
if (normalize) {
|
||||||
data.set_data3(vertex * mat);
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LVector3 vector = data.get_data3();
|
||||||
|
vector *= xform;
|
||||||
|
vector.normalize();
|
||||||
|
data.set_data3(vector);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LVector3 vector = data.get_data3();
|
||||||
|
data.set_data3(vector * xform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1965,6 +2003,25 @@ table_xform_point3f(unsigned char *datat, size_t num_rows, size_t stride,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::table_xform_normal3f
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Transforms each of the LVector3f objects in the
|
||||||
|
// indicated table by the indicated matrix, and also
|
||||||
|
// normalizes them.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
table_xform_normal3f(unsigned char *datat, size_t num_rows, size_t stride,
|
||||||
|
const LMatrix4f &matf) {
|
||||||
|
// We don't bother checking for the unaligned case here, because in
|
||||||
|
// practice it doesn't matter with a 3-component vector.
|
||||||
|
for (size_t i = 0; i < num_rows; ++i) {
|
||||||
|
LNormalf &vertex = *(LNormalf *)(&datat[i * stride]);
|
||||||
|
vertex *= matf;
|
||||||
|
vertex.normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::table_xform_vector3f
|
// Function: GeomVertexData::table_xform_vector3f
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
|
@ -334,6 +334,8 @@ private:
|
|||||||
const LMatrix4 &mat, int begin_row, int end_row);
|
const LMatrix4 &mat, int begin_row, int end_row);
|
||||||
static void table_xform_point3f(unsigned char *datat, size_t num_rows,
|
static void table_xform_point3f(unsigned char *datat, size_t num_rows,
|
||||||
size_t stride, const LMatrix4f &matf);
|
size_t stride, const LMatrix4f &matf);
|
||||||
|
static void table_xform_normal3f(unsigned char *datat, size_t num_rows,
|
||||||
|
size_t stride, const LMatrix4f &matf);
|
||||||
static void table_xform_vector3f(unsigned char *datat, size_t num_rows,
|
static void table_xform_vector3f(unsigned char *datat, size_t num_rows,
|
||||||
size_t stride, const LMatrix4f &matf);
|
size_t stride, const LMatrix4f &matf);
|
||||||
static void table_xform_vecbase4f(unsigned char *datat, size_t num_rows,
|
static void table_xform_vecbase4f(unsigned char *datat, size_t num_rows,
|
||||||
|
@ -825,6 +825,7 @@ do_register() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case C_vector:
|
case C_vector:
|
||||||
|
case C_normal:
|
||||||
// It's a vector.
|
// It's a vector.
|
||||||
_vectors.push_back(column->get_name());
|
_vectors.push_back(column->get_name());
|
||||||
break;
|
break;
|
||||||
@ -1017,7 +1018,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector));
|
NT_stdfloat, C_normal));
|
||||||
|
|
||||||
_v3t2 = register_format(new GeomVertexArrayFormat
|
_v3t2 = register_format(new GeomVertexArrayFormat
|
||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
@ -1029,7 +1030,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector,
|
NT_stdfloat, C_normal,
|
||||||
InternalName::get_texcoord(), 2,
|
InternalName::get_texcoord(), 2,
|
||||||
NT_stdfloat, C_texcoord));
|
NT_stdfloat, C_texcoord));
|
||||||
|
|
||||||
@ -1044,7 +1045,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector,
|
NT_stdfloat, C_normal,
|
||||||
InternalName::get_color(), 1,
|
InternalName::get_color(), 1,
|
||||||
NT_packed_dabc, C_color));
|
NT_packed_dabc, C_color));
|
||||||
|
|
||||||
@ -1060,7 +1061,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector,
|
NT_stdfloat, C_normal,
|
||||||
InternalName::get_color(), 1,
|
InternalName::get_color(), 1,
|
||||||
NT_packed_dabc, C_color,
|
NT_packed_dabc, C_color,
|
||||||
InternalName::get_texcoord(), 2,
|
InternalName::get_texcoord(), 2,
|
||||||
@ -1079,7 +1080,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector,
|
NT_stdfloat, C_normal,
|
||||||
InternalName::get_color(), 4,
|
InternalName::get_color(), 4,
|
||||||
NT_uint8, C_color));
|
NT_uint8, C_color));
|
||||||
|
|
||||||
@ -1095,7 +1096,7 @@ make_standard_formats() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
NT_stdfloat, C_point,
|
NT_stdfloat, C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
NT_stdfloat, C_vector,
|
NT_stdfloat, C_normal,
|
||||||
InternalName::get_color(), 4,
|
InternalName::get_color(), 4,
|
||||||
NT_uint8, C_color,
|
NT_uint8, C_color,
|
||||||
InternalName::get_texcoord(), 2,
|
InternalName::get_texcoord(), 2,
|
||||||
|
@ -63,7 +63,7 @@ generate_block(unsigned short mx,
|
|||||||
array->add_column(InternalName::get_texcoord(), 2,
|
array->add_column(InternalName::get_texcoord(), 2,
|
||||||
Geom::NT_stdfloat, Geom::C_texcoord);
|
Geom::NT_stdfloat, Geom::C_texcoord);
|
||||||
array->add_column(InternalName::get_normal(), 3,
|
array->add_column(InternalName::get_normal(), 3,
|
||||||
Geom::NT_stdfloat, Geom::C_vector);
|
Geom::NT_stdfloat, Geom::C_normal);
|
||||||
|
|
||||||
PT(GeomVertexFormat) format = new GeomVertexFormat();
|
PT(GeomVertexFormat) format = new GeomVertexFormat();
|
||||||
format->add_array(array);
|
format->add_array(array);
|
||||||
|
@ -1062,7 +1062,7 @@ make_array_format(const VisColumns &vis_columns) const {
|
|||||||
case CT_normal3:
|
case CT_normal3:
|
||||||
num_components = 3;
|
num_components = 3;
|
||||||
numeric_type = GeomEnums::NT_float32;
|
numeric_type = GeomEnums::NT_float32;
|
||||||
contents = GeomEnums::C_vector;
|
contents = GeomEnums::C_normal;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CT_blend1:
|
case CT_blend1:
|
||||||
@ -1072,7 +1072,7 @@ make_array_format(const VisColumns &vis_columns) const {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nassertr(num_components != 0, NULL);
|
nassertr(num_components != 0, NULL);
|
||||||
|
|
||||||
array_format->add_column(name, num_components, numeric_type, contents);
|
array_format->add_column(name, num_components, numeric_type, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ get_format(bool support_normals) const {
|
|||||||
if (support_normals && get_normal_mode() == NM_vertex) {
|
if (support_normals && get_normal_mode() == NM_vertex) {
|
||||||
array_format->add_column
|
array_format->add_column
|
||||||
(InternalName::get_normal(), 3, Geom::NT_stdfloat,
|
(InternalName::get_normal(), 3, Geom::NT_stdfloat,
|
||||||
Geom::C_vector);
|
Geom::C_normal);
|
||||||
}
|
}
|
||||||
if (get_use_vertex_color()) {
|
if (get_use_vertex_color()) {
|
||||||
array_format->add_column
|
array_format->add_column
|
||||||
|
Loading…
x
Reference in New Issue
Block a user