📄 t3dlib6.cpp
字号:
// 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 + -