⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t3dlib7.cpp

📁 3D游戏编程大师技巧第九章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                               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 + -