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

📄 t3dlib7.cpp

📁 3D游戏编程大师技巧第九章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -