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

📄 raiders3d_2b.cpp

📁 3D游戏编程大师技巧第九章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
          // we want to use the screen coords of the energy burst this is fine, but a more effective method
          // would be to compute the 3D world coords of where the energy burst is firing and then project
          // that parallelpiped in 3D space to see where the player is trying to fire, this is a classic
          // problem with screen picking, hence, in the engine, when an object is rendered sometimes its 
          // a good idea to track somekind of collision boundary in screen coords that can be used later
          // for "object picking" and collision, anyway, let's do it the easy way, but the long way....

          // first is the player firing weapon?
          if (weapon_active)
             {
             // we need 4 transforms total, first we need all our points in world coords,
             // then we need camera coords, then perspective coords, then screen coords

             // we need to transform 2 points: the center and a point lying on the surface of the  
             // bounding sphere, as long as the 

             POINT4D pbox[4], // bounding box coordinates, center points, surrounding object
                              // denoted by X's, we need to project these to screen coords
                              // ....X.... 
                              // . |   | .
                              // X |-O-| X
                              // . |   | . 
                              // ....X....
                              // we will use the average radius as the distance to each X from the center

                     presult; // used to hold temp results

             // world to camera transform

             // transform center point only
             Mat_Mul_VECTOR4D_4X4(&obj_alien.world_pos, &cam.mcam, &presult);

             // result holds center of object in camera coords now
             // now we are in camera coords, aligned to z-axis, compute radial point axis aligned
             // bounding box points

             // x+r, y, z
             pbox[0].x = presult.x + obj_alien.avg_radius[obj_alien.curr_frame];
             pbox[0].y = presult.y;
             pbox[0].z = presult.z;
             pbox[0].w = 1;        

             // x-r, y, z
             pbox[1].x = presult.x - obj_alien.avg_radius[obj_alien.curr_frame];
             pbox[1].y = presult.y;
             pbox[1].z = presult.z;
             pbox[1].w = 1;     

             // x, y+r, z
             pbox[2].x = presult.x;
             pbox[2].y = presult.y + obj_alien.avg_radius[obj_alien.curr_frame];
             pbox[2].z = presult.z;
             pbox[2].w = 1;     

             // x, y-r, z
             pbox[3].x = presult.x;
             pbox[3].y = presult.y - obj_alien.avg_radius[obj_alien.curr_frame];
             pbox[3].z = presult.z;
             pbox[3].w = 1;     


             // now we are ready to project the points to screen space
             float alpha = (0.5*cam.viewport_width-0.5);
             float beta  = (0.5*cam.viewport_height-0.5);

             // loop and process each point
             for (int bindex=0; bindex < 4; bindex++)
                 {
                 float z = pbox[bindex].z;

                 // perspective transform first
                 pbox[bindex].x = cam.view_dist*pbox[bindex].x/z;
                 pbox[bindex].y = cam.view_dist*pbox[bindex].y*cam.aspect_ratio/z;
                 // z = z, so no change

                 // screen projection
                 pbox[bindex].x =  alpha*pbox[bindex].x + alpha; 
                 pbox[bindex].y = -beta*pbox[bindex].y + beta;

                 } // end for bindex

#ifdef DEBUG_ON
             // now we have the 4 points is screen coords and we can test them!!! ya!!!!
             Draw_Clip_Line16(pbox[0].x, pbox[2].y, pbox[1].x, pbox[2].y, rgb_red, back_buffer, back_lpitch);
             Draw_Clip_Line16(pbox[0].x, pbox[3].y, pbox[1].x, pbox[3].y, rgb_red, back_buffer, back_lpitch);

             Draw_Clip_Line16(pbox[0].x, pbox[2].y, pbox[0].x, pbox[3].y, rgb_red, back_buffer, back_lpitch);
             Draw_Clip_Line16(pbox[1].x, pbox[2].y, pbox[1].x, pbox[3].y, rgb_red, back_buffer, back_lpitch);
#endif

             // test for collision
             if ((cross_x_screen > pbox[1].x) && (cross_x_screen < pbox[0].x) &&
                 (cross_y_screen > pbox[2].y) && (cross_y_screen < pbox[3].y) )
                {
                Start_Mesh_Explosion(&obj_alien, // object to blow
                                     &mrot,      // initial orientation
                                     3,          // the detail level,1 highest detail
                                     .5,         // velocity of explosion shrapnel
                                     100);       // total lifetime of explosion         

                // remove from simulation
                aliens[index].state = ALIEN_STATE_DEAD;

                // make some sound
                DSound_Play(explosion_id);

                // increment hits
                hits++;
              
                // take into consideration the z, the speed, the level, blah blah
                score += (int)((diff_level*10 + obj_alien.world_pos.z/10));

                } // end if
        
             } // end if weapon active

          } break;
         
          default: break;

          } // end switch

    } // end for index

// debug code

#ifdef DEBUG_ON
// reset the object (this only matters for backface and object removal)
Reset_OBJECT4DV2(&obj_alien);
static int ang_y = 0;
// generate rotation matrix around y axis
Build_XYZ_Rotation_MATRIX4X4(0, ang_y++, 0 ,&mrot);
         
// rotate the local coords of the object
Transform_OBJECT4DV2(&obj_alien, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);

// set position of constant shaded cube
obj_alien.world_pos.x = px;
obj_alien.world_pos.y = py;
obj_alien.world_pos.z = pz;

// perform world transform
Model_To_World_OBJECT4DV2(&obj_alien, TRANSFORM_TRANS_ONLY);

// insert the object into render list
Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_alien,0);
#endif

} // end Draw_Aliens

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

void Draw_Mesh_Explosions(void)
{
// this function draws the mesh explosions
MATRIX4X4 mrot; // used to transform objects

// draw the explosions, note we do NOT cull them
for (int eindex = 0; eindex < NUM_EXPLOSIONS; eindex++)
    {
    // is the mesh explosions active
    if ((explobj[eindex].state & OBJECT4DV2_STATE_ACTIVE))
       {
       // reset the object
       Reset_OBJECT4DV2(&explobj[eindex]);

       // generate rotation matrix 
       Build_XYZ_Rotation_MATRIX4X4(0, 0, 0 ,&mrot);
         
       // rotate the local coords of the object
       Transform_OBJECT4DV2(&explobj[eindex], &mrot, TRANSFORM_LOCAL_TO_TRANS,1);

       // perform world transform
       Model_To_World_OBJECT4DV2(&explobj[eindex], TRANSFORM_TRANS_ONLY);

       // insert the object into render list
       Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &explobj[eindex],0);
   
       // now animate the mesh
       VECTOR4D_PTR trajectory = (VECTOR4D_PTR)explobj[eindex].ivar1;
       
       for (int pindex = 0; pindex < explobj[eindex].num_polys; pindex++)
           {
           // vertex 0
           VECTOR4D_Add(&explobj[eindex].vlist_local[pindex*3 + 0].v,
                        &trajectory[pindex*2+0], 
                        &explobj[eindex].vlist_local[pindex*3 + 0].v);

           // vertex 1
           VECTOR4D_Add(&explobj[eindex].vlist_local[pindex*3 + 1].v,
                        &trajectory[pindex*2 + 0], 
                        &explobj[eindex].vlist_local[pindex*3 + 1].v);

           // vertex 2
           VECTOR4D_Add(&explobj[eindex].vlist_local[pindex*3 + 2].v,
                        &trajectory[pindex*2 + 0], 
                        &explobj[eindex].vlist_local[pindex*3 + 2].v);

           // modulate color
           //explobj[eindex].plist[pindex].color = RGB16Bit(rand()%255,0,0);

           } // end for pindex

      // update counter, test for terminate
      if (--explobj[eindex].ivar2 < 0)
         {
         // reset this object
         explobj[eindex].state  = OBJECT4DV2_STATE_NULL;           

         // release memory of object, but only data that isn't linked to master object
         // local vertex list
         if (explobj[eindex].head_vlist_local)
            free(explobj[eindex].head_vlist_local);

         // transformed vertex list
         if (explobj[eindex].head_vlist_trans)
            free(explobj[eindex].head_vlist_trans);

         // polygon list
         if (explobj[eindex].plist)
            free(explobj[eindex].plist);

         // trajectory list
         if ((VECTOR4D_PTR)(explobj[eindex].ivar1))
            free((VECTOR4D_PTR)explobj[eindex].ivar1);

         // now clear out object completely
         memset((void *)&explobj[eindex], 0, sizeof(OBJECT4DV2));

         } // end if 

       } // end if  

    } // end for eindex
 
} // end Draw_Mesh_Explosions

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

int Start_Mesh_Explosion(OBJECT4DV2_PTR obj,  // object to destroy
                         MATRIX4X4_PTR mrot, // initial orientation of object
                         int detail,          // the detail level,1 highest detail
                         float rate,          // velocity of explosion shrapnel
                         int lifetime)        // total lifetime of explosion
{
// this function "blows up" an object, it takes a pointer to the object to
// be destroyed, the detail level of the polyogonal explosion, 1 is high detail, 
// numbers greater than 1 are lower detail, the detail selects the polygon extraction
// stepping, hence a detail of 5 would mean every 5th polygon in the original mesh
// should be part of the explosion, on average no more than 10-50% of the polygons in 
// the original mesh should be used for the explosion; some would be vaporized and
// in a more practical sense, when an object is far, there's no need to have detail
// the next parameter is the rate which is used as a general scale for the explosion
// velocity, and finally lifetime which is the number of cycles to display the explosion

// the function works by taking the original object then copying the core information
// except for the polygon and vertex lists, the function operates by selecting polygon 
// by polygon to be destroyed and then makes a copy of the polygon AND all of it's vertices,
// thus the vertex coherence is completely lost, this is a necessity since each polygon must
// be animated separately by the engine, thus they can't share vertices, additionally at the
// end if the vertex list will be the velocity and rotation information for each polygon
// this is hidden to the rest of the engine, now for the explosion, the center of the object
// is used as the point of origin then a ray is drawn thru each polygon, then each polygon
// is thrown at some velocity with a small rotation rate
// finally the system can only have so many explosions at one time

// step: 1 find an available explosion
for (int eindex = 0; eindex < NUM_EXPLOSIONS; eindex++)
    {
    // is this explosion available?
    if (explobj[eindex].state == OBJECT4DV2_STATE_NULL)
       {
       // copy the object, including the pointers which we will unlink shortly...
       explobj[eindex]                =  *obj;

       explobj[eindex].state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;

       // recompute a few things
       explobj[eindex].num_polys      = obj->num_polys/detail;
       explobj[eindex].num_vertices   = 3*obj->num_polys;
       explobj[eindex].total_vertices = 3*obj->num_polys; // one frame only
      
       // unlink/re-allocate all the pointers except the texture coordinates, we can use those, they don't
       // depend on vertex coherence
       // allocate memory for vertex lists
       if (!(explobj[eindex].vlist_local = (VERTEX4DTV1_PTR)malloc(sizeof(VERTEX4DTV1)*explobj[eindex].num_vertices)))
          return(0);

       // clear data
       memset((void *)explobj[eindex].vlist_local,0,sizeof(VERTEX4DTV1)*explobj[eindex].num_vertices);

       if (!(explobj[eindex].vlist_trans = (VERTEX4DTV1_PTR)malloc(sizeof(VERTEX4DTV1)*explobj[eindex].num_vertices)))
           return(0);

       // clear data
       memset((void *)explobj[eindex].vlist_trans,0,sizeof(VERTEX4DTV1)*explobj[eindex].num_vertices);

       // allocate memory for polygon list
       if (!(explobj[eindex].plist = (POLY4DV2_PTR)malloc(sizeof(POLY4DV2)*explobj[eindex].num_polys)))
          return(0);

       // clear data
       memset((void *)explobj[eindex].plist,0,sizeof(POLY4DV2)*explobj[eindex].num_polys);

       // now, we need somewhere to store the vector trajectories of the polygons and their rotational rates
       // so let's allocate an array of VECTOR4D elements to hold this information and then store it
       // in ivar1, therby using ivar as a pointer, this is perfectly fine :)
       // each record will consist of a velocity and a rotational rate in x,y,z, so V0,R0, V1,R1,...Vn-1, Rn-1
       // allocate memory for polygon list
       if (!(explobj[eindex].ivar1 = (int)malloc(sizeof(VECTOR4D)*2*explobj[eindex].num_polys)))
          return(0);

       // clear data
       memset((void *)explobj[eindex].ivar1,0,sizeof(VECTOR4D)*2*explobj[eindex].num_polys);

       // alias working pointer
       VECTOR4D_PTR trajectory = (VECTOR4D_PTR)explobj[eindex].ivar1;

       // these are needed to track the "head" of the vertex list for multi-frame objects
       explobj[eindex].head_vlist_local = explobj[eindex].vlist_local;
       explobj[eindex].head_vlist_trans = explobj[eindex].vlist_trans;

       // set the lifetime in ivar2
       explobj[eindex].ivar2 = lifetime;

       // now comes the tricky part, loop and copy each polygon, but as we copy the polygons, we have to copy
       // the vertices, and insert them, and fix up the vertice indices etc.
       for (int pindex = 0; pindex < explobj[eindex].num_polys; pindex++)
           {
           // alright, we want to copy the (pindex*detail)th poly from the master to the (pindex)th
           // polygon in explosion
           explobj[eindex].plist[pindex] = obj->plist[pindex*detail];

           // we need to modify, the vertex list pointer and the vertex indices themselves
           explobj[eindex].plist[pindex].vlist = explobj[eindex].vlist_local;

           // now comes the hard part, we need to first copy the vertices from the original mesh
           // into the new vertex storage, but at the same time keep the same vertex ordering
          
           // vertex 0
           explobj[eindex].plist[pindex].vert[0] = pindex*3 + 0;
           explobj[eindex].vlist_local[pindex*3 + 0] = obj->vlist_local[ obj->plist[pindex*detail].vert[0] ];

           // vertex 1
           explobj[eindex].plist[pindex].vert[1] = pindex*3 + 1;
           explobj[eindex].vlist_local[pindex*3 + 1] = obj->vlist_local[ obj->plist[pindex*detail].vert[1] ];

           // vertex 2
           explobj[eindex].plist[pindex].vert[2] = pindex*3 + 2;
           explobj[eindex].vlist_local[pindex*3 + 2] = obj->vlist_local[ obj->plist[pindex*detail].vert[2] ];

           // reset shading flag to constant for some of the shrapnel since they are giving off light 
           if ((rand()%5) == 1)
              {
              SET_BIT(explobj[eindex].plist[pindex].attr, POLY4DV2_ATTR_SHADE_MODE_PURE);
              RESET_BIT(explobj[eindex].plist[pindex].attr, POLY4DV2_ATTR_SHADE_MODE_GOURAUD);
              RESET_BIT(explobj[eindex].plist[pindex].attr, POLY4DV2_ATTR_SHADE_MODE_FLAT);

              // set color
              explobj[eindex].plist[pindex].color = RGB16Bit(128+rand()%128,0,0);

              } // end if

           // add some random noise to trajectory
           static VECTOR4D mv;
       
           // first compute trajectory as vector from center to vertex piercing polygon
           VECTOR4D_INIT(&trajectory[pindex*2+0], &obj->vlist_local[ obj->plist[pindex*detail].vert[0] ].v);
           VECTOR4D_Scale(rate, &trajectory[pindex*2+0], &trajectory[pindex*2+0]);          
         
           mv.x = RAND_RANGE(-10,10);

⌨️ 快捷键说明

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