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

📄 t3dlib6.cpp

📁 3D游戏编程大师技巧第九章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

// cache vars
int bwidth = bitmap->bitmapinfoheader.biWidth;
int bheight = bitmap->bitmapinfoheader.biHeight;

// allocate temporary buffer
USHORT *buffer16 = (USHORT *)malloc(bwidth * bheight * 2);

// for each pixel in the bitmap convert it to a 16 bit value
for (int pixel = 0; pixel < bwidth*bheight; pixel++)
    {
    // get 8-bit color index
    int cindex = bitmap->buffer[pixel];

    // build 16-bit pixel with extractd RGB values for the pixel in palette
    buffer16[pixel] = RGB16Bit(bitmap->palette[cindex].peRed, 
                               bitmap->palette[cindex].peGreen,
                               bitmap->palette[cindex].peBlue);
    } // end for

// now change file information, actually not much has changed, but what the heck
bitmap->bitmapinfoheader.biBitCount     = 16; 
bitmap->bitmapinfoheader.biSizeImage    = bwidth*bheight*2;
bitmap->bitmapinfoheader.biWidth        = bwidth;
bitmap->bitmapinfoheader.biHeight       = bheight;
bitmap->bitmapinfoheader.biClrUsed      = 0;
bitmap->bitmapinfoheader.biClrImportant = 0;

// finally copy temp buffer
free( bitmap->buffer );

// link new buffer
bitmap->buffer = (UCHAR *)buffer16;

#if 1
// write the file info out 
printf("\nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
        bitmap->bitmapinfoheader.biSizeImage,
        bitmap->bitmapinfoheader.biWidth,
        bitmap->bitmapinfoheader.biHeight,
		bitmap->bitmapinfoheader.biBitCount,
        bitmap->bitmapinfoheader.biClrUsed,
        bitmap->bitmapinfoheader.biClrImportant);
#endif

// return success
return(1);

} // end Convert_Bitmap_8_16

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

int Load_OBJECT4DV1_3DSASC(OBJECT4DV1_PTR obj,   // pointer to object
                           char *filename,       // filename of ASC file
                           VECTOR4D_PTR scale,   // initial scaling factors
                           VECTOR4D_PTR pos,     // initial position
                           VECTOR4D_PTR rot,     // initial rotations
                           int vertex_flags)     // flags to re-order vertices
{
// this function loads a 3D Studi .ASC file object in off disk, additionally
// it allows the caller to scale, position, and rotate the object
// to save extra calls later for non-dynamic objects
// create a parser object
CPARSERV1 parser; 

char seps[16];          // seperators for token scanning
char token_buffer[256]; // used as working buffer for token
char *token;            // pointer to next token

int r,g,b;              // working colors


// Step 1: clear out the object and initialize it a bit
memset(obj, 0, sizeof(OBJECT4DV1));

// set state of object to active and visible
obj->state = OBJECT4DV1_STATE_ACTIVE | OBJECT4DV1_STATE_VISIBLE;

// set position of object is caller requested position
if (pos)
   {
   // set position of object
   obj->world_pos.x = pos->x;
   obj->world_pos.y = pos->y;
   obj->world_pos.z = pos->z;
   obj->world_pos.w = pos->w;
   } // end 
else
   {
   // set it to (0,0,0,1)
   obj->world_pos.x = 0;
   obj->world_pos.y = 0;
   obj->world_pos.z = 0;
   obj->world_pos.w = 1;
   } // end else

// Step 2: open the file for reading using the parser
if (!parser.Open(filename))
   {
   Write_Error("Couldn't open .ASC file %s.", filename);
   return(0);
   } // end if

// Step 3: 

// lets find the name of the object first 
while(1)
     {
     // get the next line, we are looking for "Named object:"
     if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
        {
        Write_Error("Image 'name' not found in .ASC file %s.", filename);
        return(0);
        } // end if
    
     // check for pattern?  
     if (parser.Pattern_Match(parser.buffer, "['Named'] ['object:']"))
        {
        // at this point we have the string with the name in it, parse it out by finding 
        // name between quotes "name...."
        strcpy(token_buffer, parser.buffer);
        strcpy(seps, "\"");        
        strtok( token_buffer, seps );
        
        // this will be the token between the quotes
        token = strtok(NULL, seps);
      
        // copy name into structure
        strcpy(obj->name, token);          
        Write_Error("\nASC Reader Object Name: %s", obj->name);

        break;    
        } // end if

     } // end while

// step 4: get number of vertices and polys in object
while(1)
     {
     // get the next line, we are looking for "Tri-mesh, Vertices:" 
     if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
        {
        Write_Error("'Tri-mesh' line not found in .ASC file %s.", filename);
        return(0);
        } // end if
    
     // check for pattern?  
     if (parser.Pattern_Match(parser.buffer, "['Tri-mesh,'] ['Vertices:'] [i] ['Faces:'] [i]"))
        {
        // simply extract the number of vertices and polygons from the pattern matching 
        // output arrays
        obj->num_vertices = parser.pints[0];
        obj->num_polys    = parser.pints[1];

        Write_Error("\nASC Reader Num Vertices: %d, Num Polys: %d", 
                    obj->num_vertices, obj->num_polys);
        break;    
 
        } // end if

     } // end while

// Step 5: load the vertex list

// advance parser to vertex list denoted by:
// "Vertex list:"
while(1)
     {
     // get next line
     if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
        {
        Write_Error("\n'Vertex list:' line not found in .ASC file %s.", filename);
        return(0);
        } // end if
    
     // check for pattern?  
     if (parser.Pattern_Match(parser.buffer, "['Vertex'] ['list:']"))
        {
        Write_Error("\nASC Reader found vertex list in .ASC file %s.", filename);
        break;
        } // end if
     } // end while

// now read in vertex list, format:
// "Vertex: d  X:d.d Y:d.d  Z:d.d"
 for (int vertex = 0; vertex < obj->num_vertices; vertex++)
     {
     // hunt for vertex
     while(1)
     {
     // get the next vertex
     if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
        {
        Write_Error("\nVertex list ended abruptly! in .ASC file %s.", filename);
        return(0);
        } // end if
    
     // strip all ":XYZ", make this easier, note use of input and output as same var, this is legal
     // since the output is guaranteed to be the same length or shorter as the input :)
     StripChars(parser.buffer, parser.buffer, ":XYZ");
     
     // check for pattern?  
     if (parser.Pattern_Match(parser.buffer, "['Vertex'] [i] [f] [f] [f]"))
        {
        // at this point we have the x,y,z in the the pfloats array locations 0,1,2
        obj->vlist_local[vertex].x = parser.pfloats[0];
        obj->vlist_local[vertex].y = parser.pfloats[1];
        obj->vlist_local[vertex].z = parser.pfloats[2];
        obj->vlist_local[vertex].w = 1;

        // do vertex swapping right here, allow muliple swaps, why not!
        // defines for vertex re-ordering flags

        //#define VERTEX_FLAGS_INVERT_X   1    // inverts the Z-coordinates
        //#define VERTEX_FLAGS_INVERT_Y   2    // inverts the Z-coordinates
        //#define VERTEX_FLAGS_INVERT_Z   4    // inverts the Z-coordinates
        //#define VERTEX_FLAGS_SWAP_YZ    8    // transforms a RHS model to a LHS model
        //#define VERTEX_FLAGS_SWAP_XZ    16   // ???
        //#define VERTEX_FLAGS_SWAP_XY    32
        //#define VERTEX_FLAGS_INVERT_WINDING_ORDER 64  // invert winding order from cw to ccw or ccw to cc

        float temp_f; // used for swapping

        // invert signs?
        if (vertex_flags & VERTEX_FLAGS_INVERT_X)
           obj->vlist_local[vertex].x=-obj->vlist_local[vertex].x;

        if (vertex_flags & VERTEX_FLAGS_INVERT_Y)
           obj->vlist_local[vertex].y=-obj->vlist_local[vertex].y;

        if (vertex_flags & VERTEX_FLAGS_INVERT_Z)
           obj->vlist_local[vertex].z=-obj->vlist_local[vertex].z;

        // swap any axes?
        if (vertex_flags & VERTEX_FLAGS_SWAP_YZ)
           SWAP(obj->vlist_local[vertex].y, obj->vlist_local[vertex].z, temp_f);
        
        if (vertex_flags & VERTEX_FLAGS_SWAP_XZ)
           SWAP(obj->vlist_local[vertex].x, obj->vlist_local[vertex].z, temp_f);

        if (vertex_flags & VERTEX_FLAGS_SWAP_XY)
           SWAP(obj->vlist_local[vertex].x, obj->vlist_local[vertex].y, temp_f);

        Write_Error("\nVertex %d = %f, %f, %f, %f", vertex,
                                           obj->vlist_local[vertex].x, 
                                           obj->vlist_local[vertex].y, 
                                           obj->vlist_local[vertex].z,
                                           obj->vlist_local[vertex].w);

        // scale vertices
        if (scale)
           {
           obj->vlist_local[vertex].x*=scale->x;
           obj->vlist_local[vertex].y*=scale->y;
           obj->vlist_local[vertex].z*=scale->z;
           } // end if

        // found vertex, break out of while for next pass
        break;

        } // end if

    } // end while

    } // end for vertex

// compute average and max radius
Compute_OBJECT4DV1_Radius(obj);

Write_Error("\nObject average radius = %f, max radius = %f", 
            obj->avg_radius, obj->max_radius);

// step 6: load in the polygons
// poly list starts off with:
// "Face list:"
while(1)
     {
     // get next line
     if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
        {
        Write_Error("\n'Face list:' line not found in .ASC file %s.", filename);
        return(0);
        } // end if
    
     // check for pattern?  
     if (parser.Pattern_Match(parser.buffer, "['Face'] ['list:']"))
        {
        Write_Error("\nASC Reader found face list in .ASC file %s.", filename);
        break;
        } // end if
     } // end while

// now read each face in format:
// Face ddd:    A:ddd B:ddd C:ddd AB:1|0 BC:1|0 CA:1|
// Material:"rdddgdddbddda0"
// the A, B, C part is vertex 0,1,2 but the AB, BC, CA part
// has to do with the edges and the vertex ordering
// the material indicates the color, and has an 'a0' tacked on the end???

int  poly_surface_desc = 0; // ASC surface descriptor/material in this case
int  poly_num_verts    = 0; // number of vertices for current poly (always 3)
char tmp_string[8];         // temp string to hold surface descriptor in and
                            // test if it need to be converted from hex

for (int poly=0; poly < obj->num_polys; poly++)
    {
    // hunt until next face is found
    while(1)
    {
    // get the next polygon face
    if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
       {
       Write_Error("\nface list ended abruptly! in .ASC file %s.", filename);
       return(0);
       } // end if
    
    // strip all ":ABC", make this easier, note use of input and output as same var, this is legal
    // since the output is guaranteed to be the same length or shorter as the input :)
    StripChars(parser.buffer, parser.buffer, ":ABC");
     
    // check for pattern?  
    if (parser.Pattern_Match(parser.buffer, "['Face'] [i] [i] [i] [i]"))
       {
       // at this point we have the vertex indices in the the pints array locations 1,2,3, 
       // 0 contains the face number

       // insert polygon, check for winding order invert
       if (vertex_flags & VERTEX_FLAGS_INVERT_WINDING_ORDER)
          {     
          poly_num_verts           = 3;
          obj->plist[poly].vert[0] = parser.pints[3];
          obj->plist[poly].vert[1] = parser.pints[2];
          obj->plist[poly].vert[2] = parser.pints[1];
          } // end if
       else
          { // leave winding order alone
          poly_num_verts           = 3;
          obj->plist[poly].vert[0] = parser.pints[1];
          obj->plist[poly].vert[1] = parser.pints[2];
          obj->plist[poly].vert[2] = parser.pints[3];
          } // end else

       // point polygon vertex list to object's vertex list
       // note that this is redundant since the polylist is contained
       // within the object in this case and its up to the user to select
       // whether the local or transformed vertex list is used when building up
       // polygon geometry, might be a better idea to set to NULL in the context
       // of polygons that are part of an object
       obj->plist[poly].vlist = obj->vlist_local; 
  
       // found the face, break out of while for another pass
       break;

       } // end if
 
     } // end while      

    // hunt until next material for face is found
    while(1)
    {
    // get the next polygon material (the "page xxx" breaks mess everything up!!!)
    if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
       {
       Write_Error("\nmaterial list ended abruptly! in .ASC file %s.", filename);
       return(0);
       } // end if
    
    // Material:"rdddgdddbddda0"
    // replace all ':"rgba', make this easier, note use of input and output as same var, this is legal
    // since the output is guaranteed to be the same length or shorter as the input :)
    // the result will look like:
    // "M t ri l   ddd ddd ddd 0" 
    // which we can parse!
    ReplaceChars(parser.buffer, parser.buffer, ":\"rgba", ' ');
     
    // check for pattern?  
    if (parser.Pattern_Match(parser.buffer, "[i] [i] [i]"))
       {
       // at this point we have the red, green, and blue components in the the pints array locations 0,1,2, 
       r = parser.pints[0];
       g = parser.pints[1];
       b = parser.pints[2];

       // set all the attributes of polygon as best we can with this format
       // SET_BIT(obj->plist[poly].attr, POLY4DV1_ATTR_2SIDED);
    
       // we need to know what color depth we are dealing with, so check
       // the bits per pixel, this assumes that the system has already
       // made the call to DDraw_Init() or set the bit depth
       if (screen_bpp==16)
          {
          // cool, 16 bit mode
          SET_BIT(obj->plist[poly].attr,POLY4DV1_ATTR_RGB16);

⌨️ 快捷键说明

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