This commit is contained in:
David Rose 2008-12-27 01:42:50 +00:00
parent ea2f07943a
commit a9825fe78f
4 changed files with 155 additions and 29 deletions

View File

@ -636,27 +636,72 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
GeomVertexReader rcolor, rnormal;
// We now support up to 2-stage multitexturing.
GeomVertexReader rtexcoord[MAX_TEXTURE_STAGES];
bool needs_texcoord[MAX_TEXTURE_STAGES] = { false, false };
bool needs_texmat[MAX_TEXTURE_STAGES] = { false, false };
LMatrix4f texmat[MAX_TEXTURE_STAGES];
const InternalName *texcoord_name[MAX_TEXTURE_STAGES] = {
InternalName::get_texcoord(), InternalName::get_texcoord()
};
GenTexcoordFunc *texgen_func[MAX_TEXTURE_STAGES];
TexCoordData tcdata[MAX_TEXTURE_STAGES];
const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
int max_stage_index = _target_texture->get_num_on_ff_stages();
for (int si = 0; si < max_stage_index; ++si) {
TextureStage *stage = _target_texture->get_on_ff_stage(si);
rtexcoord[si] = GeomVertexReader(data_reader, stage->get_texcoord_name(),
force);
rtexcoord[si].set_row(_min_vertex);
needs_texcoord[si] = rtexcoord[si].has_column();
if (needs_texcoord[si]) {
const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
if (target_tex_matrix->has_stage(stage)) {
needs_texmat[si] = true;
texmat[si] = target_tex_matrix->get_mat(stage);
switch (target_tex_gen->get_mode(stage)) {
case TexGenAttrib::M_eye_sphere_map:
tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_normal(),
force);
tcdata[si]._r2 = GeomVertexReader(data_reader, InternalName::get_vertex(),
force);
texgen_func[si] = &texgen_sphere_map;
tcdata[si]._mat = _internal_transform->get_mat();
break;
case TexGenAttrib::M_eye_position:
tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
force);
texgen_func[si] = &texgen_texmat;
{
CPT(TransformState) eye_transform =
_cs_transform->invert_compose(_internal_transform);
tcdata[si]._mat = eye_transform->get_mat();
}
if (target_tex_matrix->has_stage(stage)) {
tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
}
break;
case TexGenAttrib::M_world_position:
tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
force);
texgen_func[si] = &texgen_texmat;
{
CPT(TransformState) render_transform =
_cs_transform->compose(_scene_setup->get_world_transform());
CPT(TransformState) world_transform =
_internal_transform->invert_compose(render_transform);
tcdata[si]._mat = world_transform->get_mat();
}
if (target_tex_matrix->has_stage(stage)) {
tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
}
break;
default:
// Fall through: use the standard texture coordinates.
tcdata[si]._r1 = GeomVertexReader(data_reader, stage->get_texcoord_name(),
force);
texgen_func[si] = &texgen_simple;
if (target_tex_matrix->has_stage(stage)) {
texgen_func[si] = &texgen_texmat;
tcdata[si]._mat = target_tex_matrix->get_mat(stage);
}
break;
}
tcdata[si]._r1.set_row(_min_vertex);
tcdata[si]._r2.set_row(_min_vertex);
if (!tcdata[si]._r1.has_column()) {
texgen_func[si] = &texgen_null;
}
}
@ -722,18 +767,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
// Texture coordinates.
for (int si = 0; si < max_stage_index; ++si) {
if (needs_texmat[si]) {
// Transform texcoords as a four-component vector for most generality.
LVecBase4f d = rtexcoord[si].get_data4f() * texmat[si];
v->tex_coord[si].v[0] = d[0];
v->tex_coord[si].v[1] = d[1];
} else if (needs_texcoord[si]) {
// No need to transform, so just extract as two-component.
const LVecBase2f &d = rtexcoord[si].get_data2f();
v->tex_coord[si].v[0] = d[0];
v->tex_coord[si].v[1] = d[1];
}
TexCoordf d;
(*texgen_func[si])(v->tex_coord[si], tcdata[si]);
}
if (needs_color) {
@ -2974,3 +3009,76 @@ get_tex_filter_func(Texture::FilterType filter) {
}
}
////////////////////////////////////////////////////////////////////
// Function: TinyGraphicsStateGuardian::texgen_null
// Access: Private, Static
// Description: Generates invalid texture coordinates. Used when
// texture coordinate params are invalid or unsupported.
////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian::
texgen_null(V2 &result, TinyGraphicsStateGuardian::TexCoordData &) {
result.v[0] = 0.0;
result.v[1] = 0.0;
}
////////////////////////////////////////////////////////////////////
// Function: TinyGraphicsStateGuardian::texgen_simple
// Access: Private, Static
// Description: Extracts a simple 2-d texture coordinate pair from
// the vertex data, without applying any texture matrix.
////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian::
texgen_simple(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
// No need to transform, so just extract as two-component.
const LVecBase2f &d = tcdata._r1.get_data2f();
result.v[0] = d[0];
result.v[1] = d[1];
}
////////////////////////////////////////////////////////////////////
// Function: TinyGraphicsStateGuardian::texgen_simple
// Access: Private, Static
// Description: Extracts a simple 2-d texture coordinate pair from
// the vertex data, and then applies a texture matrix.
////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian::
texgen_texmat(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
// Transform texcoords as a four-component vector for most generality.
LVecBase4f d = tcdata._r1.get_data4f() * tcdata._mat;
result.v[0] = d[0] / d[3];
result.v[1] = d[1] / d[3];
}
////////////////////////////////////////////////////////////////////
// Function: TinyGraphicsStateGuardian::texgen_sphere_map
// Access: Private, Static
// Description: Computes appropriate sphere map texture coordinates
// based on the eye normal coordinates.
////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian::
texgen_sphere_map(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
// Get the normal and point in eye coordinates.
LVector3f n = tcdata._mat.xform_vec(tcdata._r1.get_data3f());
LVector3f u = tcdata._mat.xform_point(tcdata._r2.get_data3f());
// Normalize the vectors.
n.normalize();
u.normalize();
// Compute the reflection vector.
LVector3f r = u - n * dot(n, u) * 2.0f;
// compute the denominator, m.
float m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
// Now we can compute the s and t coordinates.
result.v[0] = r[0] / m + 0.5f;
result.v[1] = r[1] / m + 0.5f;
/*
cerr << "n = " << n << " u = " << u << "\n"
<< " r = " << r << "\n"
<< " m = " << m << ", result = " << result.v[0] << " " << result.v[1]
<< "\n";
*/
}

View File

@ -23,6 +23,7 @@
#include "zmath.h"
#include "zbuffer.h"
#include "zgl.h"
#include "geomVertexReader.h"
class TinyTextureContext;
@ -127,6 +128,19 @@ private:
INLINE void clear_light_state();
// Methods used to generate texture coordinates.
class TexCoordData {
public:
GeomVertexReader _r1;
GeomVertexReader _r2;
LMatrix4f _mat;
};
typedef void GenTexcoordFunc(V2 &result, TexCoordData &tcdata);
static void texgen_null(V2 &result, TexCoordData &tcdata);
static void texgen_simple(V2 &result, TexCoordData &tcdata);
static void texgen_texmat(V2 &result, TexCoordData &tcdata);
static void texgen_sphere_map(V2 &result, TexCoordData &tcdata);
public:
// Filled in by the Tiny*GraphicsWindow at begin_frame().
ZBuffer *_current_frame_buffer;

View File

@ -105,7 +105,7 @@ typedef struct GLVertex {
int edge_flag;
V3 normal;
V4 coord;
V4 tex_coord[MAX_TEXTURE_STAGES];
V2 tex_coord[MAX_TEXTURE_STAGES];
V4 color;
/* computed values */

View File

@ -15,6 +15,10 @@ typedef struct {
float m[3][4];
} M34;
typedef struct {
float v[2];
} V2;
typedef struct {
float v[3];
} V3;