mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -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) {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
|
||||
|
||||
if (normal_type != (const GeomVertexColumn *)NULL) {
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2240,7 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
if (vertex_pool->has_normals()) {
|
||||
array_format->add_column
|
||||
(InternalName::get_normal(), 3,
|
||||
Geom::NT_stdfloat, Geom::C_vector);
|
||||
Geom::NT_stdfloat, Geom::C_normal);
|
||||
}
|
||||
|
||||
if (!ignore_color) {
|
||||
|
@ -139,6 +139,9 @@ operator << (ostream &out, GeomEnums::Contents contents) {
|
||||
|
||||
case GeomEnums::C_matrix:
|
||||
return out << "matrix";
|
||||
|
||||
case GeomEnums::C_normal:
|
||||
return out << "normal";
|
||||
}
|
||||
|
||||
return out << "**invalid contents (" << (int)contents << ")**";
|
||||
|
@ -192,7 +192,7 @@ PUBLISHED:
|
||||
C_other, // Arbitrary meaning, leave it alone
|
||||
C_point, // A point in 3-space or 4-space
|
||||
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_color, // 3- or 4-component color, ordered R, G, B, [A]
|
||||
C_index, // An index value into some other table
|
||||
@ -201,6 +201,10 @@ PUBLISHED:
|
||||
// A transformation matrix. This is typically three or four
|
||||
// columns, but we pretend it's only one for convenience.
|
||||
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
|
||||
|
@ -394,8 +394,11 @@ align_columns_for_animation() {
|
||||
Columns::const_iterator ci;
|
||||
for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
|
||||
GeomVertexColumn *column = (*ci);
|
||||
if ((column->get_contents() == C_point || column->get_contents() == C_vector) &&
|
||||
(column->get_numeric_type() == NT_float32 || column->get_numeric_type() == NT_float64) &&
|
||||
if ((column->get_contents() == C_point ||
|
||||
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) {
|
||||
add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
|
||||
} else {
|
||||
|
@ -340,6 +340,11 @@ make_packer() const {
|
||||
break;
|
||||
}
|
||||
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:
|
||||
// Otherwise, we just read it as a generic value.
|
||||
switch (get_numeric_type()) {
|
||||
|
@ -1915,10 +1915,37 @@ do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &da
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
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();
|
||||
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) &&
|
||||
data_column->get_numeric_type() == NT_float32) {
|
||||
// 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;
|
||||
unsigned char *datat = data_handle->get_write_pointer();
|
||||
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);
|
||||
} else {
|
||||
table_xform_vecbase4f(datat, num_rows, stride, matf);
|
||||
@ -1939,11 +1968,20 @@ do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &d
|
||||
|
||||
} else {
|
||||
// Use the GeomVertexRewriter to transform the vectors.
|
||||
|
||||
data.set_row_unsafe(begin_row);
|
||||
for (int j = begin_row; j < end_row; ++j) {
|
||||
LVector3 vertex = data.get_data3();
|
||||
data.set_data3(vertex * mat);
|
||||
|
||||
if (normalize) {
|
||||
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
|
||||
// Access: Private, Static
|
||||
|
@ -334,6 +334,8 @@ private:
|
||||
const LMatrix4 &mat, int begin_row, int end_row);
|
||||
static void table_xform_point3f(unsigned char *datat, size_t num_rows,
|
||||
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,
|
||||
size_t stride, const LMatrix4f &matf);
|
||||
static void table_xform_vecbase4f(unsigned char *datat, size_t num_rows,
|
||||
|
@ -825,6 +825,7 @@ do_register() {
|
||||
break;
|
||||
|
||||
case C_vector:
|
||||
case C_normal:
|
||||
// It's a vector.
|
||||
_vectors.push_back(column->get_name());
|
||||
break;
|
||||
@ -1017,7 +1018,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector));
|
||||
NT_stdfloat, C_normal));
|
||||
|
||||
_v3t2 = register_format(new GeomVertexArrayFormat
|
||||
(InternalName::get_vertex(), 3,
|
||||
@ -1029,7 +1030,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector,
|
||||
NT_stdfloat, C_normal,
|
||||
InternalName::get_texcoord(), 2,
|
||||
NT_stdfloat, C_texcoord));
|
||||
|
||||
@ -1044,7 +1045,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector,
|
||||
NT_stdfloat, C_normal,
|
||||
InternalName::get_color(), 1,
|
||||
NT_packed_dabc, C_color));
|
||||
|
||||
@ -1060,7 +1061,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector,
|
||||
NT_stdfloat, C_normal,
|
||||
InternalName::get_color(), 1,
|
||||
NT_packed_dabc, C_color,
|
||||
InternalName::get_texcoord(), 2,
|
||||
@ -1079,7 +1080,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector,
|
||||
NT_stdfloat, C_normal,
|
||||
InternalName::get_color(), 4,
|
||||
NT_uint8, C_color));
|
||||
|
||||
@ -1095,7 +1096,7 @@ make_standard_formats() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
NT_stdfloat, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_stdfloat, C_vector,
|
||||
NT_stdfloat, C_normal,
|
||||
InternalName::get_color(), 4,
|
||||
NT_uint8, C_color,
|
||||
InternalName::get_texcoord(), 2,
|
||||
|
@ -63,7 +63,7 @@ generate_block(unsigned short mx,
|
||||
array->add_column(InternalName::get_texcoord(), 2,
|
||||
Geom::NT_stdfloat, Geom::C_texcoord);
|
||||
array->add_column(InternalName::get_normal(), 3,
|
||||
Geom::NT_stdfloat, Geom::C_vector);
|
||||
Geom::NT_stdfloat, Geom::C_normal);
|
||||
|
||||
PT(GeomVertexFormat) format = new GeomVertexFormat();
|
||||
format->add_array(array);
|
||||
|
@ -1062,7 +1062,7 @@ make_array_format(const VisColumns &vis_columns) const {
|
||||
case CT_normal3:
|
||||
num_components = 3;
|
||||
numeric_type = GeomEnums::NT_float32;
|
||||
contents = GeomEnums::C_vector;
|
||||
contents = GeomEnums::C_normal;
|
||||
break;
|
||||
|
||||
case CT_blend1:
|
||||
@ -1072,7 +1072,7 @@ make_array_format(const VisColumns &vis_columns) const {
|
||||
break;
|
||||
}
|
||||
nassertr(num_components != 0, NULL);
|
||||
|
||||
|
||||
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) {
|
||||
array_format->add_column
|
||||
(InternalName::get_normal(), 3, Geom::NT_stdfloat,
|
||||
Geom::C_vector);
|
||||
Geom::C_normal);
|
||||
}
|
||||
if (get_use_vertex_color()) {
|
||||
array_format->add_column
|
||||
|
Loading…
x
Reference in New Issue
Block a user