📄 t3dlib7.cpp
字号:
// T3DLIB7.CPP - low level line and triangle rendering code
// I N C L U D E S ///////////////////////////////////////////////////////////
#define DEBUG_ON
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <objbase.h>
#include <iostream.h> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <wchar.h>
#include <limits.h>
#include <float.h>
#include <search.h>
#include <ddraw.h> // needed for defs in T3DLIB1.H
#include "T3DLIB1.H"
#include "T3DLIB4.H"
#include "T3DLIB5.H"
#include "T3DLIB6.H"
#include "T3DLIB7.H"
// DEFINES //////////////////////////////////////////////////////////////////
// GLOBALS //////////////////////////////////////////////////////////////////
// this array is used to quickly compute the nearest power of 2 for a number from 0-256
// and always rounds down
// basically it's the log (b2) of n, but returns an integer
// logbase2ofx[x] = (int)log2 x, [x:0-512]
UCHAR logbase2ofx[513] =
{
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
};
char texture_path[80] = "./"; // root path to ALL textures, make current directory for now
UCHAR rgblightlookup[4096][256]; // rgb 8.12 lighting table lookup
// FUNCTIONS ////////////////////////////////////////////////////////////////
// setting the frame is so important that it should be a member function
int OBJECT4DV2::Set_Frame(int frame)
{
// this functions sets the current frame in a multi frame object
// if the object is not multiframed then the function has no effect
// test if object is valid?
if (!this)
return(0);
// test if its multiframe?
if (!(this->attr & OBJECT4DV2_ATTR_MULTI_FRAME))
return(0);
// we have a valid object and its multiframe, vector pointers to frame data
// check bounds on frame
if (frame < 0 )
frame = 0;
else
if (frame >= this->num_frames)
frame = this->num_frames - 1;
// set frame
this->curr_frame = frame;
// update pointers to point to "block" of vertices that represent this frame
// the vertices from each frame are 1-1 and onto relative to the polygons that
// make up the object, they are simply shifted, this we need to re-vector the
// pointers based on the head pointers
this->vlist_local = &(this->head_vlist_local[frame*this->num_vertices]);
this->vlist_trans = &(this->head_vlist_trans[frame*this->num_vertices]);
// return success
return(1);
} // end Set_Frame
///////////////////////////////////////////////////////////////////////////////
int Set_OBJECT4DV2_Frame(OBJECT4DV2_PTR obj, int frame)
{
// this functions sets the current frame in a multi frame object
// if the object is not multiframed then the function has no effect
// totally external function
// test if object is valid?
if (!obj)
return(0);
// test if its multiframe?
if (!(obj->attr & OBJECT4DV2_ATTR_MULTI_FRAME))
return(0);
// we have a valid object and its multiframe, vector pointers to frame data
// check bounds on frame
if (frame < 0 )
frame = 0;
else
if (frame >= obj->num_frames)
frame = obj->num_frames - 1;
// set frame
obj->curr_frame = frame;
// update pointers to point to "block" of vertices that represent this frame
// the vertices from each frame are 1-1 and onto relative to the polygons that
// make up the object, they are simply shifted, this we need to re-vector the
// pointers based on the head pointers
obj->vlist_local = &(obj->head_vlist_local[frame*obj->num_vertices]);
obj->vlist_trans = &(obj->head_vlist_trans[frame*obj->num_vertices]);
// return success
return(1);
} // end Set_Frame
////////////////////////////////////////////////////////////////////////////////
int Destroy_OBJECT4DV2(OBJECT4DV2_PTR obj) // object to destroy
{
// this function destroys the sent object, basically frees the memory
// if any that has been allocated
// local vertex list
if (obj->head_vlist_local)
free(obj->head_vlist_local);
// transformed vertex list
if (obj->head_vlist_trans)
free(obj->head_vlist_trans);
// texture coordinate list
if (obj->tlist)
free(obj->tlist);
// polygon list
if (obj->plist)
free(obj->plist);
// object radii arrays
if (obj->avg_radius)
free(obj->avg_radius);
if (obj->max_radius)
free(obj->max_radius);
// now clear out object completely
memset((void *)obj, 0, sizeof(OBJECT4DV2));
// return success
return(1);
} // end Destroy_OBJECT4DV2
////////////////////////////////////////////////////////////////////////////////
int Init_OBJECT4DV2(OBJECT4DV2_PTR obj, // object to allocate
int _num_vertices,
int _num_polys,
int _num_frames,
int destroy)
{
// this function does nothing more than allocate the memory for an OBJECT4DV2
// based on the sent data, later we may want to create more robust initializers
// but the problem is that we don't want to tie the initializer to anthing yet
// in 99% of cases this all will be done by the call to load object
// we just might need this function if we manually want to build an object???
// first destroy the object if it exists
if (destroy)
Destroy_OBJECT4DV2(obj);
// allocate memory for vertex lists
if (!(obj->vlist_local = (VERTEX4DTV1_PTR)malloc(sizeof(VERTEX4DTV1)*_num_vertices*_num_frames)))
return(0);
// clear data
memset((void *)obj->vlist_local,0,sizeof(VERTEX4DTV1)*_num_vertices*_num_frames);
if (!(obj->vlist_trans = (VERTEX4DTV1_PTR)malloc(sizeof(VERTEX4DTV1)*_num_vertices*_num_frames)))
return(0);
// clear data
memset((void *)obj->vlist_trans,0,sizeof(VERTEX4DTV1)*_num_vertices*_num_frames);
// number of texture coordinates always 3*number of polys
if (!(obj->tlist = (POINT2D_PTR)malloc(sizeof(POINT2D)*_num_polys*3)))
return(0);
// clear data
memset((void *)obj->tlist,0,sizeof(POINT2D)*_num_polys*3);
// allocate memory for radii arrays
if (!(obj->avg_radius = (float *)malloc(sizeof(float)*_num_frames)))
return(0);
// clear data
memset((void *)obj->avg_radius,0,sizeof(float)*_num_frames);
if (!(obj->max_radius = (float *)malloc(sizeof(float)*_num_frames)))
return(0);
// clear data
memset((void *)obj->max_radius,0,sizeof(float)*_num_frames);
// allocate memory for polygon list
if (!(obj->plist = (POLY4DV2_PTR)malloc(sizeof(POLY4DV2)*_num_polys)))
return(0);
// clear data
memset((void *)obj->plist,0,sizeof(POLY4DV2)*_num_polys);
// alias head pointers
obj->head_vlist_local = obj->vlist_local;
obj->head_vlist_trans = obj->vlist_trans;
// set some internal variables
obj->num_frames = _num_frames;
obj->num_polys = _num_polys;
obj->num_vertices = _num_vertices;
obj->total_vertices = _num_vertices*_num_frames;
// return success
return(1);
} // end Init_OBJECT4DV2
//////////////////////////////////////////////////////////////
void Translate_OBJECT4DV2(OBJECT4DV2_PTR obj, VECTOR4D_PTR vt)
{
// NOTE: Not matrix based
// this function translates an object without matrices,
// simply updates the world_pos
VECTOR4D_Add(&obj->world_pos, vt, &obj->world_pos);
} // end Translate_OBJECT4DV2
/////////////////////////////////////////////////////////////
void Scale_OBJECT4DV2(OBJECT4DV2_PTR obj, VECTOR4D_PTR vs, int all_frames)
{
// NOTE: Not matrix based
// this function scales and object without matrices
// modifies the object's local vertex list
// additionally the radii is updated for the object
// for each vertex in the mesh scale the local coordinates by
// vs on a componentwise basis, that is, sx, sy, sz
// also, since the object may hold multiple frames this update
// will ONLY scale the currently selected frame in default mode
// unless all_frames = 1, in essence the function emulates version 1
// for single frame objects
// also, normal lengths will change if the object is scaled!
// so we must scale those too, we simple need to scale the length of
// each normal n*(sx*sy*sz)
if (!all_frames)
{
// perform transform on selected frame only
for (int vertex=0; vertex < obj->num_vertices; vertex++)
{
obj->vlist_local[vertex].x*=vs->x;
obj->vlist_local[vertex].y*=vs->y;
obj->vlist_local[vertex].z*=vs->z;
// leave w unchanged, always equal to 1
} // end for vertex
// now since the object is scaled we have to do something with
// the radii calculation, but we don't know how the scaling
// factors relate to the original major axis of the object,
// therefore for scaling factors all ==1 we will simple multiply
// which is correct, but for scaling factors not equal to 1, we
// must take the largest scaling factor and use it to scale the
// radii with since it's the worst case scenario of the new max and
// average radii, the ONLY reason we do this is to keep the function
// fast, you may want to recompute the radii if you need the accuracy
// find max scaling factor
float scale = MAX(vs->x, vs->y);
scale = MAX(scale, vs->z);
// now scale current frame
obj->max_radius[obj->curr_frame]*=scale;
obj->avg_radius[obj->curr_frame]*=scale;
} // end if
else //
{
// perform transform
for (int vertex=0; vertex < obj->total_vertices; vertex++)
{
obj->head_vlist_local[vertex].x*=vs->x;
obj->head_vlist_local[vertex].y*=vs->y;
obj->head_vlist_local[vertex].z*=vs->z;
// leave w unchanged, always equal to 1
} // end for vertex
// now since the object is scaled we have to do something with
// the radii calculation, but we don't know how the scaling
// factors relate to the original major axis of the object,
// therefore for scaling factors all ==1 we will simple multiply
// which is correct, but for scaling factors not equal to 1, we
// must take the largest scaling factor and use it to scale the
// radii with since it's the worst case scenario of the new max and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -