📄 t3dlib7.cpp
字号:
int all_frames)
{
// NOTE: Not matrix based
// this function converts the local model coordinates of the
// sent object into world coordinates, the results are stored
// in the transformed vertex list (vlist_trans) within the object
// interate thru vertex list and transform all the model/local
// coords to world coords by translating the vertex list by
// the amount world_pos and storing the results in vlist_trans[]
// no need to transform vertex normals, they are invariant of position
if (!all_frames)
{
if (coord_select == TRANSFORM_LOCAL_TO_TRANS)
{
for (int vertex=0; vertex < obj->num_vertices; vertex++)
{
// translate vertex
VECTOR4D_Add(&obj->vlist_local[vertex].v, &obj->world_pos, &obj->vlist_trans[vertex].v);
// copy normal
VECTOR4D_COPY(&obj->vlist_trans[vertex].n, &obj->vlist_local[vertex].n);
} // end for vertex
} // end if local
else
{ // TRANSFORM_TRANS_ONLY
for (int vertex=0; vertex < obj->num_vertices; vertex++)
{
// translate vertex
VECTOR4D_Add(&obj->vlist_trans[vertex].v, &obj->world_pos, &obj->vlist_trans[vertex].v);
} // end for vertex
} // end else trans
} // end if single frame
else // all frames
{
if (coord_select == TRANSFORM_LOCAL_TO_TRANS)
{
for (int vertex=0; vertex < obj->total_vertices; vertex++)
{
// translate vertex
VECTOR4D_Add(&obj->head_vlist_local[vertex].v, &obj->world_pos, &obj->head_vlist_trans[vertex].v);
// copy normal
VECTOR4D_COPY(&obj->head_vlist_trans[vertex].n, &obj->head_vlist_local[vertex].n);
} // end for vertex
} // end if local
else
{ // TRANSFORM_TRANS_ONLY
for (int vertex=0; vertex < obj->total_vertices; vertex++)
{
// translate vertex
VECTOR4D_Add(&obj->head_vlist_trans[vertex].v, &obj->world_pos, &obj->head_vlist_trans[vertex].v);
} // end for vertex
} // end else trans
} // end if all frames
} // end Model_To_World_OBJECT4DV2
//////////////////////////////////////////////////////////////////////
int Cull_OBJECT4DV2(OBJECT4DV2_PTR obj, // object to cull
CAM4DV1_PTR cam, // camera to cull relative to
int cull_flags) // clipping planes to consider
{
// NOTE: is matrix based
// this function culls an entire object from the viewing
// frustrum by using the sent camera information and object
// the cull_flags determine what axes culling should take place
// x, y, z or all which is controlled by ORing the flags
// together
// if the object is culled its state is modified thats all
// this function assumes that both the camera and the object
// are valid!
// also for OBJECT4DV2, only the current frame matters for culling
// step 1: transform the center of the object's bounding
// sphere into camera space
POINT4D sphere_pos; // hold result of transforming center of bounding sphere
// transform point
Mat_Mul_VECTOR4D_4X4(&obj->world_pos, &cam->mcam, &sphere_pos);
// step 2: based on culling flags remove the object
if (cull_flags & CULL_OBJECT_Z_PLANE)
{
// cull only based on z clipping planes
// test far plane
if ( ((sphere_pos.z - obj->max_radius[obj->curr_frame]) > cam->far_clip_z) ||
((sphere_pos.z + obj->max_radius[obj->curr_frame]) < cam->near_clip_z) )
{
SET_BIT(obj->state, OBJECT4DV2_STATE_CULLED);
return(1);
} // end if
} // end if
if (cull_flags & CULL_OBJECT_X_PLANE)
{
// cull only based on x clipping planes
// we could use plane equations, but simple similar triangles
// is easier since this is really a 2D problem
// if the view volume is 90 degrees the the problem is trivial
// buts lets assume its not
// test the the right and left clipping planes against the leftmost and rightmost
// points of the bounding sphere
float z_test = (0.5)*cam->viewplane_width*sphere_pos.z/cam->view_dist;
if ( ((sphere_pos.x-obj->max_radius[obj->curr_frame]) > z_test) || // right side
((sphere_pos.x+obj->max_radius[obj->curr_frame]) < -z_test) ) // left side, note sign change
{
SET_BIT(obj->state, OBJECT4DV2_STATE_CULLED);
return(1);
} // end if
} // end if
if (cull_flags & CULL_OBJECT_Y_PLANE)
{
// cull only based on y clipping planes
// we could use plane equations, but simple similar triangles
// is easier since this is really a 2D problem
// if the view volume is 90 degrees the the problem is trivial
// buts lets assume its not
// test the the top and bottom clipping planes against the bottommost and topmost
// points of the bounding sphere
float z_test = (0.5)*cam->viewplane_height*sphere_pos.z/cam->view_dist;
if ( ((sphere_pos.y-obj->max_radius[obj->curr_frame]) > z_test) || // top side
((sphere_pos.y+obj->max_radius[obj->curr_frame]) < -z_test) ) // bottom side, note sign change
{
SET_BIT(obj->state, OBJECT4DV2_STATE_CULLED);
return(1);
} // end if
} // end if
// return failure to cull
return(0);
} // end Cull_OBJECT4DV2
/////////////////////////////////////////////////////////////////////////////
void Remove_Backfaces_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list, CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function removes the backfaces from polygon list
// the function does this based on the polygon list data
// tvlist along with the camera position (only)
// note that only the backface state is set in each polygon
for (int poly = 0; poly < rend_list->num_polys; poly++)
{
// acquire current polygon
POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
// is this polygon valid?
// test this polygon if and only if it's not clipped, not culled,
// active, and visible and not 2 sided. Note we test for backface in the event that
// a previous call might have already determined this, so why work
// harder!
if ((curr_poly==NULL) || !(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
(curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
(curr_poly->attr & POLY4DV2_ATTR_2SIDED) ||
(curr_poly->state & POLY4DV2_STATE_BACKFACE) )
continue; // move onto next poly
// we need to compute the normal of this polygon face, and recall
// that the vertices are in cw order, u = p0->p1, v=p0->p2, n=uxv
VECTOR4D u, v, n;
// build u, v
VECTOR4D_Build(&curr_poly->tvlist[0].v, &curr_poly->tvlist[1].v, &u);
VECTOR4D_Build(&curr_poly->tvlist[0].v, &curr_poly->tvlist[2].v, &v);
// compute cross product
VECTOR4D_Cross(&u, &v, &n);
// now create eye vector to viewpoint
VECTOR4D view;
VECTOR4D_Build(&curr_poly->tvlist[0].v, &cam->pos, &view);
// and finally, compute the dot product
float dp = VECTOR4D_Dot(&n, &view);
// if the sign is > 0 then visible, 0 = scathing, < 0 invisible
if (dp <= 0.0 )
SET_BIT(curr_poly->state, POLY4DV2_STATE_BACKFACE);
} // end for poly
} // end Remove_Backfaces_RENDERLIST4DV2
////////////////////////////////////////////////////////////
void Remove_Backfaces_OBJECT4DV2(OBJECT4DV2_PTR obj, CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function removes the backfaces from an object's
// polygon mesh, the function does this based on the vertex
// data in vlist_trans along with the camera position (only)
// note that only the backface state is set in each polygon
// also since this works on polygons the current frame is the frame
// that's vertices are used by the backface cull
// note: only operates on the current frame
// test if the object is culled
if (obj->state & OBJECT4DV2_STATE_CULLED)
return;
// process each poly in mesh
for (int poly=0; poly < obj->num_polys; poly++)
{
// acquire polygon
POLY4DV2_PTR curr_poly = &obj->plist[poly];
// is this polygon valid?
// test this polygon if and only if it's not clipped, not culled,
// active, and visible and not 2 sided. Note we test for backface in the event that
// a previous call might have already determined this, so why work
// harder!
if (!(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
(curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
(curr_poly->attr & POLY4DV2_ATTR_2SIDED) ||
(curr_poly->state & POLY4DV2_STATE_BACKFACE) )
continue; // move onto next poly
// extract vertex indices into master list, rember the polygons are
// NOT self contained, but based on the vertex list stored in the object
// itself
int vindex_0 = curr_poly->vert[0];
int vindex_1 = curr_poly->vert[1];
int vindex_2 = curr_poly->vert[2];
// we will use the transformed polygon vertex list since the backface removal
// only makes sense at the world coord stage further of the pipeline
// we need to compute the normal of this polygon face, and recall
// that the vertices are in cw order, u = p0->p1, v=p0->p2, n=uxv
VECTOR4D u, v, n;
// build u, v
VECTOR4D_Build(&obj->vlist_trans[ vindex_0 ].v, &obj->vlist_trans[ vindex_1 ].v, &u);
VECTOR4D_Build(&obj->vlist_trans[ vindex_0 ].v, &obj->vlist_trans[ vindex_2 ].v, &v);
// compute cross product
VECTOR4D_Cross(&u, &v, &n);
// now create eye vector to viewpoint
VECTOR4D view;
VECTOR4D_Build(&obj->vlist_trans[ vindex_0 ].v, &cam->pos, &view);
// and finally, compute the dot product
float dp = VECTOR4D_Dot(&n, &view);
// if the sign is > 0 then visible, 0 = scathing, < 0 invisible
if (dp <= 0.0 )
SET_BIT(curr_poly->state, POLY4DV2_STATE_BACKFACE);
} // end for poly
} // end Remove_Backfaces_OBJECT4DV2
////////////////////////////////////////////////////////////
void World_To_Camera_OBJECT4DV2(OBJECT4DV2_PTR obj, CAM4DV1_PTR cam)
{
// NOTE: this is a matrix based function
// this function transforms the world coordinates of an object
// into camera coordinates, based on the sent camera matrix
// but it totally disregards the polygons themselves,
// it only works on the vertices in the vlist_trans[] list
// this is one way to do it, you might instead transform
// the global list of polygons in the render list since you
// are guaranteed that those polys represent geometry that
// has passed thru backfaces culling (if any)
// note: only operates on the current frame
// transform each vertex in the object to camera coordinates
// assumes the object has already been transformed to world
// coordinates and the result is in vlist_trans[]
for (int vertex = 0; vertex < obj->num_vertices; vertex++)
{
// transform the vertex by the mcam matrix within the camera
// it better be valid!
POINT4D presult; // hold result of each transformation
// transform point
Mat_Mul_VECTOR4D_4X4(&obj->vlist_trans[vertex].v, &cam->mcam, &presult);
// store result back
VECTOR4D_COPY(&obj->vlist_trans[vertex].v, &presult);
} // end for vertex
} // end World_To_Camera_OBJECT4DV2
////////////////////////////////////////////////////////
void Camera_To_Perspective_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list,
CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function transforms each polygon in the global render list
// into perspective coordinates, based on the
// sent camera object,
// you would use this function instead of the object based function
// if you decided earlier in the pipeline to turn each object into
// a list of polygons and then add them to the global render list
// transform each polygon in the render list into camera coordinates
// assumes the render list has already been transformed to world
// coordinates and the result is in tvlist[] of each polygon object
for (int poly = 0; poly < rend_list->num_polys; poly++)
{
// acquire current polygon
POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
// is this polygon valid?
// transform this polygon if and only if it's not clipped, not culled,
// active, and visible, note however the concept of "backface" is
// irrelevant in a wire frame engine though
if ((curr_poly==NULL) || !(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
(curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
(curr_poly->state & POLY4DV2_STATE_BACKFACE) )
continue; // move onto next poly
// all good, let's transform
for (int vertex = 0; vertex < 3; vertex++)
{
float z = curr_poly->tvlist[vertex].z;
// transform the vertex by the view parameters in the camera
curr_poly->tvlist[vertex].x = cam->view_dist*curr_poly->tvlist[vertex].x/z;
curr_poly->tvlist[vertex].y = cam->view_dist*curr_poly->tvlist[vertex].y*cam->aspect_ratio/z;
// z = z, so no change
// not that we are NOT dividing by the homogenous w coordinate since
// we are not using a matrix operation for this version of the function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -