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

📄 t3dlib5.cpp

📁 3D游戏编程大师技巧第十章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    
    // 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 ], &obj->vlist_trans[ vindex_1 ], &u);
    VECTOR4D_Build(&obj->vlist_trans[ vindex_0 ], &obj->vlist_trans[ vindex_2 ], &v);

    // compute cross product
    VECTOR4D_Cross(&u, &v, &n);

    // now create eye vector to viewpoint
    VECTOR4D view;
    VECTOR4D_Build(&obj->vlist_trans[ vindex_0 ], &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, POLY4DV1_STATE_BACKFACE);

    } // end for poly

} // end Remove_Backfaces_OBJECT4DV1

////////////////////////////////////////////////////////////

void Remove_Backfaces_RENDERLIST4DV1(RENDERLIST4DV1_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
    POLYF4DV1_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 & POLY4DV1_STATE_ACTIVE) ||
        (curr_poly->state & POLY4DV1_STATE_CLIPPED ) || 
        (curr_poly->attr  & POLY4DV1_ATTR_2SIDED)    ||
        (curr_poly->state & POLY4DV1_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], &curr_poly->tvlist[1], &u);
        VECTOR4D_Build(&curr_poly->tvlist[0], &curr_poly->tvlist[2], &v);

        // compute cross product
        VECTOR4D_Cross(&u, &v, &n);

        // now create eye vector to viewpoint
        VECTOR4D view;
        VECTOR4D_Build(&curr_poly->tvlist[0], &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, POLY4DV1_STATE_BACKFACE);

         } // end for poly

} // end Remove_Backfaces_RENDERLIST4DV1

////////////////////////////////////////////////////////////

void World_To_Camera_OBJECT4DV1(OBJECT4DV1_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)

// 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], &cam->mcam, &presult);

    // store result back
    VECTOR4D_COPY(&obj->vlist_trans[vertex], &presult); 
    } // end for vertex

} // end World_To_Camera_OBJECT4DV1

////////////////////////////////////////////////////////////

void Camera_To_Perspective_OBJECT4DV1(OBJECT4DV1_PTR obj, CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function transforms the camera coordinates of an object
// into perspective coordinates, based on the 
// sent camera object, 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)
// finally this function is really for experimental reasons only
// you would probably never let an object stay intact this far down
// the pipeline, since it's probably that there's only a single polygon
// that is visible! But this function has to transform the whole mesh!

// transform each vertex in the object to perspective coordinates
// assumes the object has already been transformed to camera
// coordinates and the result is in vlist_trans[]
for (int vertex = 0; vertex < obj->num_vertices; vertex++)
    {
    float z = obj->vlist_trans[vertex].z;

    // transform the vertex by the view parameters in the camera
    obj->vlist_trans[vertex].x = cam->view_dist*obj->vlist_trans[vertex].x/z;
    obj->vlist_trans[vertex].y = cam->view_dist*obj->vlist_trans[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 
  
    } // end for vertex

} // end Camera_To_Perspective_OBJECT4DV1

//////////////////////////////////////////////////////////////

void Camera_To_Perspective_Screen_OBJECT4DV1(OBJECT4DV1_PTR obj, CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function transforms the camera coordinates of an object
// into Screen scaled perspective coordinates, based on the 
// sent camera object, that is, view_dist_h and view_dist_v 
// should be set to cause the desired (width X height)
// projection of the vertices, but the function 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)
// finally this function is really for experimental reasons only
// you would probably never let an object stay intact this far down
// the pipeline, since it's probably that there's only a single polygon
// that is visible! But this function has to transform the whole mesh!
// finally, the function also inverts the y axis, so the coordinates
// generated from this function ARE screen coordinates and ready for
// rendering

float alpha = (0.5*cam->viewport_width-0.5);
float beta  = (0.5*cam->viewport_height-0.5);

// transform each vertex in the object to perspective screen coordinates
// assumes the object has already been transformed to camera
// coordinates and the result is in vlist_trans[]
for (int vertex = 0; vertex < obj->num_vertices; vertex++)
    {
    float z = obj->vlist_trans[vertex].z;

    // transform the vertex by the view parameters in the camera
    obj->vlist_trans[vertex].x = cam->view_dist*obj->vlist_trans[vertex].x/z;
    obj->vlist_trans[vertex].y = cam->view_dist*obj->vlist_trans[vertex].y/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 

    // now the coordinates are in the range x:(-viewport_width/2 to viewport_width/2)
    // and y:(-viewport_height/2 to viewport_height/2), thus we need a translation and
    // since the y-axis is inverted, we need to invert y to complete the screen 
    // transform:
    obj->vlist_trans[vertex].x =  obj->vlist_trans[vertex].x + alpha;
    obj->vlist_trans[vertex].y = -obj->vlist_trans[vertex].y + beta;

    } // end for vertex

} // end Camera_To_Perspective_Screen_OBJECT4DV1

//////////////////////////////////////////////////////////////

void Perspective_To_Screen_OBJECT4DV1(OBJECT4DV1_PTR obj, CAM4DV1_PTR cam)
{
// NOTE: this is not a matrix based function
// this function transforms the perspective coordinates of an object
// into screen coordinates, based on the sent viewport info
// 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)
// finally this function is really for experimental reasons only
// you would probably never let an object stay intact this far down
// the pipeline, since it's probably that there's only a single polygon
// that is visible! But this function has to transform the whole mesh!
// this function would be called after a perspective
// projection was performed on the object

// transform each vertex in the object to screen coordinates
// assumes the object has already been transformed to perspective
// coordinates and the result is in vlist_trans[]

float alpha = (0.5*cam->viewport_width-0.5);
float beta  = (0.5*cam->viewport_height-0.5);

for (int vertex = 0; vertex < obj->num_vertices; vertex++)
    {
    // assumes the vertex is in perspective normalized coords from -1 to 1
    // on each axis, simple scale them to viewport and invert y axis and project
    // to screen

    // transform the vertex by the view parameters in the camera
    obj->vlist_trans[vertex].x = alpha + alpha*obj->vlist_trans[vertex].x;
    obj->vlist_trans[vertex].y = beta  - beta *obj->vlist_trans[vertex].y;
  
    } // end for vertex

} // end Perspective_To_Screen_OBJECT4DV1

/////////////////////////////////////////////////////////////

void Convert_From_Homogeneous4D_OBJECT4DV1(OBJECT4DV1_PTR obj)
{
// this function convertes all vertices in the transformed
// vertex list from 4D homogeneous coordinates to normal 3D coordinates
// by dividing each x,y,z component by w

for (int vertex = 0; vertex < obj->num_vertices; vertex++)
    {
    // convert to non-homogenous coords
    VECTOR4D_DIV_BY_W(&obj->vlist_trans[vertex]);     
    } // end for vertex

} // end Convert_From_Homogeneous4D_OBJECT4DV1

/////////////////////////////////////////////////////////////

void Transform_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list, // render list to transform
                              MATRIX4X4_PTR mt,   // transformation matrix
                              int coord_select)   // selects coords to transform
{
// this function simply transforms all of the polygons vertices in the local or trans
// array of the render list by the sent matrix

// what coordinates should be transformed?
switch(coord_select)
      {
      case TRANSFORM_LOCAL_ONLY:
      {
      for (int poly = 0; poly < rend_list->num_polys; poly++)
          {
          // acquire current polygon
          POLYF4DV1_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 & POLY4DV1_STATE_ACTIVE) ||
              (curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||
              (curr_poly->state & POLY4DV1_STATE_BACKFACE) )
             continue; // move onto next poly

          // all good, let's transform 
          for (int vertex = 0; vertex < 3; vertex++)
              {
              // transform the vertex by mt
              POINT4D presult; // hold result of each transformation

              // transform point
              Mat_Mul_VECTOR4D_4X4(&curr_poly->vlist[vertex], mt, &presult);

              // store result back
              VECTOR4D_COPY(&curr_poly->vlist[vertex], &presult); 
              } // end for vertex
 
          } // end for poly

      } break;
 
      case TRANSFORM_TRANS_ONLY:
      {
      // transform each "transformed" vertex of the render list
      // remember, the idea of the tvlist[] array is to accumulate
      // transformations
      for (int poly = 0; poly < rend_list->num_polys; poly++)
          {
          // acquire current polygon
          POLYF4DV1_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 & POLY4DV1_STATE_ACTIVE) ||
              (curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||
              (curr_poly->state & POLY4DV1_STATE_BACKFACE) )
             continue; // move onto next poly

          // all good, let's transform 
          for (int vertex = 0; vertex < 3; vertex++)
              {
              // transform the vertex by mt
              POINT4D presult; // hold result of each transformation

              // transform point
              Mat_Mul_VECTOR4D_4X4(&curr_poly->tvlist[vertex], mt, &presult);

              // store result back
              VECTOR4D_COPY(&curr_poly->tvlist[vertex], &presult); 
              } // end for vertex
 
          } // end for poly

      } break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -