青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

創建3D圖形引擎(3)【OO改良版】

 

本篇是創建3D圖形引擎(2)【OO改良版】的續篇,以創建游戲內核【OO改良版】中編寫的代碼為基礎進行開發,細節說明請參閱創建3D圖形引擎(3)

 

接口:

/*************************************************************************
PURPOSE:
    Interface for node tree mesh.
*************************************************************************/


#ifndef _NODETREE_H
#define _NODETREE_H

#include "core_common.h"

float closest_height_between_object_and_mesh(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos);
float closest_height_below_object(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos);
float closest_height_above_object(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos);

BOOL is_ray_intersect_mesh(LPD3DXBASEMESH mesh,
                           
float x_start, float y_start, float z_start,
                           
float x_end, float y_end, float z_end,
                           
float* distance);

BOOL is_tow_sphere_intersect(
float x_center_1, float y_center_1, float z_center_1,
                             
float radius1,
                             
float x_center_2, float y_center_2, float z_center_2,
                             
float radius2);

///////////////////////////////// define for calss NODE_TREE_MESH /////////////////////////////////

// enumerate the two types of tree structures
enum TREE_TYPES { QUADTREE = 0, OCTREE };

//=====================================================================================
// This calss encapsulate how to divide world space.
//=====================================================================================
typedef class NODE_TREE_MESH
{
private:    
    
// The VERTEX_INFO structure is a custom vertex structure than contains only the 3D coordinates.
    // This is used to retrieve coordinate information from a mesh's vertex buffer.
    typedef struct VERTEX
    {
        
float x, y, z;
    } *VERTEX_PTR;

    
// The POLYGON_INFO structure maintains a material group index,
    // the time it was last drawn (so youo don't redraw it many times over per frame),
    // and the three vertices used to render the polygon (which you'll read on later).
    typedef struct POLYGON
    {
        
ulong   mg_index;           // material group index
        ulong   render_timer;

        
ushort  vertex_index_0;
        
ushort  vertex_index_1;
        
ushort  vertex_index_2;

        POLYGON()
        {
            memset(
this, 0, sizeof(*this));
        }
    } *POLYGON_PTR;

    
// The node structure keeps count of the number of polygons in its 3D space, polygon index list,
    // the 3D coordinates of the node (as well as the radius, which is the distance from the center to
    // one edge making the node a perfect cube), and pointers to the child nodes.
    typedef struct NODE
    {
        
float       x_pos, y_pos, z_pos;   // center coordinate of node
        float       diameter;              // diameter of node

        
ulong       num_polys;              // number of polygons in node
        ulong_ptr   poly_index_list;        // polygon index list

        NODE*       child_nodes[8];         
// child nodes information 4 = quad, 8 = oct.

        // constructor used to clear out variables
        NODE()
        {
            memset(
this, 0, sizeof(*this));
        }

        
// destructor to clear child nodes and variables
        ~NODE()
        {
            delete[] poly_index_list;
            poly_index_list = NULL;

            
// delete child nodes
            for(short i = 0; i < 8; i++)
            {
                delete child_nodes[i];
                child_nodes[i] = NULL;
            }
        }
    } *NODE_PTR;

    
// The material group structure uses IDirect3DIndexBuffer9 to store polygons vertex index
    // that need to be rendered in a single frame, also it maintains the number of polygons in
    // a material group and how many polygons to draw each frame.
    typedef struct MATERIAL_GROUP
    {
        
ulong   num_polys;          // number of polygons in group
        ulong   num_polys_to_draw;  // number of polygons to draw

        IDirect3DIndexBuffer9*  index_buffer; 
        ushort_ptr              index_ptr;

        
// clear out member data
        MATERIAL_GROUP()
        {
            memset(
this, 0, sizeof(*this));
        }

        
// free index buffer
        ~MATERIAL_GROUP()
        {
            
if(index_buffer)
                index_buffer->Release();

            index_buffer = NULL;
        }
    } *MATERIAL_GROUP_PTR;

private:
    
int                 m_tree_type;            // type of nodetree (QUADTREE or OCTREE)

    FRUSTUM_PTR         m_frustum;              
// viewing frustum

    
float               m_world_cube_diameter;  // diameter of world cube
    float               m_node_max_diameter;    // maximum node diameter

    NODE_PTR            m_root_node;            
// node list

    
ulong               m_num_mg;               // number of material group
    MATERIAL_GROUP_PTR  m_mg_list;              // material group list

    
ulong               m_max_polys_per_node;   // maximum number of polygons per node allow

    
ulong               m_num_polys;            // number of polygons in scene
    POLYGON_PTR         m_poly_list;            // list of polygons

    
ulong               m_render_timer;         // current draw timer

    MESH_INFO_PTR       m_root_mesh_info;       
// pointer to root mesh
    char_ptr            m_vertex_ptr;           // pointer to mesh vertices
    ulong               m_vertex_fvf;           // mesh vertex FVF
    ulong               m_num_bytes_per_vertex; // num bytes per vertex

private:
    
void _sort_node(NODE_PTR node,
                    
float x_pos, float y_pos, float z_pos,
                    
float diameter);

    
void _add_node(NODE_PTR node);

   BOOL _polygon_contain_in_node(POLYGON_PTR poly, 
                                  
float x_pos, float y_pos, float z_pos,
                                  
float diameter);

    
ulong _count_polygons_in_node(float x_pos, float y_pos, float z_pos,
                                  
float diameter);

public:
   NODE_TREE_MESH();
   ~NODE_TREE_MESH();

   BOOL create(MESH_PTR mesh,
               
int tree_type, float node_max_diameter, long max_polys_per_node);

   
void free();

   BOOL render(FRUSTUM_PTR frustum, 
float z_dist);

   
float closest_height_between_object_and_mesh(float x_pos, float y_pos, float z_pos);
   
float closest_height_below_object(float x_pos, float y_pos, float z_pos);
   
float closest_height_above_object(float x_pos, float y_pos, float z_pos);

   BOOL is_ray_intersect_mesh(
float x_start, float y_start, float z_start,
                              
float x_end, float y_end, float z_end,
                              
float* distance);    
} *NODE_TREE_MESH_PTR;

#endif

實現:

/*************************************************************************
PURPOSE:
    Implement for node tree mesh.
*************************************************************************/


#include "core_common.h"
#include "core_graphics.h"
#include "frustum.h"
#include "node_tree_mesh.h"

//------------------------------------------------------------------------------
// Get closest height above or below point.
//------------------------------------------------------------------------------
float closest_height_between_object_and_mesh(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos)
{
    
float y_above, y_below;

    y_above = closest_height_above_object(mesh, x_pos, y_pos, z_pos);
    y_below = closest_height_below_object(mesh, x_pos, y_pos, z_pos);

    
if(fabs(y_above - y_pos) < fabs(y_below - y_pos))
        
return y_above;

    
return y_below;
}

//------------------------------------------------------------------------------
// Get closet height below point.
//------------------------------------------------------------------------------
float closest_height_below_object(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos)
{
    BOOL is_hit;
    
float u, v, dist;
    DWORD face_index;

    D3DXVECTOR3 ray_pos(x_pos, y_pos, z_pos);
    D3DXVECTOR3 ray_dir(0.0f, -1.0f, 0.0f);

    D3DXIntersect(mesh, &ray_pos, &ray_dir, &is_hit, &face_index, &u, &v, &dist, NULL, NULL);

    
if(is_hit)
        
return y_pos - dist;

    
return y_pos;
}

//------------------------------------------------------------------------------
// Get closet height above point.
//------------------------------------------------------------------------------
float closest_height_above_object(LPD3DXBASEMESH mesh, float x_pos, float y_pos, float z_pos)
{
    BOOL is_hit;
    
float u, v, dist;
    DWORD face_index;

    D3DXVECTOR3 ray_pos(x_pos, y_pos, z_pos);
    D3DXVECTOR3 ray_dir(0.0f, 1.0f, 0.0f);

    D3DXIntersect(mesh, &ray_pos, &ray_dir, &is_hit, &face_index, &u, &v, &dist, NULL, NULL);

    
if(is_hit)
        
return y_pos + dist;

    
return y_pos;
}

//------------------------------------------------------------------------------
// Check if a polygon blocks path from start to end.
//------------------------------------------------------------------------------
BOOL is_ray_intersect_mesh(LPD3DXBASEMESH mesh,
                           
float x_start, float y_start, float z_start,
                           
float x_end, float y_end, float z_end,
                           
float* distance)
{
    
float x_diff, y_diff, z_diff;

    x_diff = x_end - x_start;
    y_diff = y_end - y_start;
    z_diff = z_end - z_start;

    D3DXVECTOR3 ray_pos(x_start, y_start, z_start);

    D3DXVECTOR3 ray_dir;
    D3DXVec3Normalize(&ray_dir, &D3DXVECTOR3(x_diff, y_diff, z_diff));

    BOOL is_hit;
    
float u, v, dist;
    DWORD face_index;

    
// determins if a ray intersects with a mesh
    D3DXIntersect(mesh, &ray_pos, &ray_dir, &is_hit, &face_index, &u, &v, &dist, NULL, NULL);

    
if(is_hit)
    {
        
float ray_length = (float) sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff);

        
if(dist > ray_length)
            
return FALSE;
        
else
        {
            
if(distance != NULL)
                *distance = dist;
        }
    }

    
return TRUE;
}

//------------------------------------------------------------------------------
// Check if two spheres intersect.
//------------------------------------------------------------------------------
BOOL is_tow_sphere_intersect(float x_center_1, float y_center_1, float z_center_1,
                             
float radius1,
                             
float x_center_2, float y_center_2, float z_center_2,
                             
float radius2)
{
    
float x_diff, y_diff, z_diff, dist;
    
    
// calculate distance between two sphere center]
    
    x_diff = fabs(x_center_2 - x_center_1);
    y_diff = fabs(y_center_2 - y_center_1);
    z_diff = fabs(z_center_2 - z_center_1);

    dist = (
float) sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff); 

    
// if two spheres intersect, retuen TRUE.
    if(dist <= radius1 + radius2)
        
return TRUE;

    
return FALSE;
}

//------------------------------------------------------------------------------
// Groups the polygons into nodes and splits the nodes into child nodes as needed.
//------------------------------------------------------------------------------
void NODE_TREE_MESH::_sort_node(NODE_PTR node,
                                
float x_pos, float y_pos, float z_pos,
                                
float diameter)
{
    
// error checking
    if(node == NULL)
        
return;

    
// store node coordinates and size
    node->x_pos    = x_pos;
    node->y_pos    = (m_tree_type == QUADTREE) ? 0.0f : y_pos;
    node->z_pos    = z_pos;
    node->diameter = diameter;

    
ulong num_polys_in_node;

    
// see if there are any polygons in the node
    if((num_polys_in_node = _count_polygons_in_node(x_pos, y_pos, z_pos, diameter)) == 0)
       
return;

    
// split node if diameter > m_node_max_diameter and too many polygons
    if(diameter > m_node_max_diameter && num_polys_in_node > m_max_polys_per_node)
    {
        
ulong divide_node_num = (m_tree_type == QUADTREE) ? 4 : 8;

        
for(ulong i = 0; i < divide_node_num; i++)
        {
            
float x_off = (((i % 2) < 1) ? -1.0f : 1.0f) * (diameter / 4);
            
float z_off = (((i % 4) < 2) ? -1.0f : 1.0f) * (diameter / 4);
            
float y_off = (((i % 8) < 4) ? -1.0f : 1.0f) * (diameter / 4);

            
// see if any polygons in new node boudning box
            if(_count_polygons_in_node(x_pos + x_off, y_pos + y_off, z_pos + z_off, diameter / 2))
            {
                node->child_nodes[i] = 
new NODE;    // create new child node

                // sort the polygons with the new child node
                _sort_node(node->child_nodes[i], x_pos + x_off, y_pos + y_off, z_pos + z_off, diameter / 2);
            }
        }

        
return;
    }

    
// allocate space for vertex index
    node->num_polys       = num_polys_in_node;
    node->poly_index_list = 
new ulong[num_polys_in_node];

    
// scan through polygon list, storing polygon index and assiging them.

    
ulong poly_index = 0;

    
for(ulong i = 0; i < m_num_polys; i++)
    {
        
// add polygon to node list if contained in 3D space
        if(_polygon_contain_in_node(&m_poly_list[i], x_pos, y_pos, z_pos, diameter))
            node->poly_index_list[poly_index++] = i;
    }
}

//------------------------------------------------------------------------------
// Check whether polygon is in node.
//------------------------------------------------------------------------------
BOOL NODE_TREE_MESH::_polygon_contain_in_node(POLYGON_PTR poly, 
                                              
float x_pos, float y_pos, float z_pos,
                                              
float diameter)
{
    
// get the polygon's vertices

    VERTEX_PTR vertex[3];

    vertex[0] = (VERTEX_PTR) &m_vertex_ptr[m_num_bytes_per_vertex * poly->vertex_index_0];
    vertex[1] = (VERTEX_PTR) &m_vertex_ptr[m_num_bytes_per_vertex * poly->vertex_index_1];
    vertex[2] = (VERTEX_PTR) &m_vertex_ptr[m_num_bytes_per_vertex * poly->vertex_index_2];

    
float x_min, x_max, y_min, y_max, z_min, z_max;

    
// check against x axis of specified 3D space
    
    x_min = min(vertex[0]->x, min(vertex[1]->x, vertex[2]->x));
    x_max = max(vertex[0]->x, max(vertex[1]->x, vertex[2]->x));

    
if(x_max < (x_pos - diameter / 2))
        
return FALSE;

    
if(x_min >  (x_pos + diameter / 2))
        
return FALSE;

    
// check against y axis of specified 3D space (only if octree tree type)
    if(m_tree_type == OCTREE)
    {
        y_min = min(vertex[0]->y, min(vertex[1]->y, vertex[2]->y));
        y_max = max(vertex[0]->y, max(vertex[1]->y, vertex[2]->y));

        
if(y_max < (y_pos - diameter / 2))
            
return FALSE;

        
if(y_min >  (y_pos + diameter / 2))
            
return FALSE;
    }

    
// check against z axis of specified 3D space

    z_min = min(vertex[0]->z, min(vertex[1]->z, vertex[2]->z));
    z_max = max(vertex[0]->z, max(vertex[1]->z, vertex[2]->z));

    
if(z_max < (z_pos - diameter / 2))
        
return FALSE;

    
if(z_min >  (z_pos + diameter / 2))
        
return FALSE;

    
return TRUE;
}

//------------------------------------------------------------------------------
// Count the number of polygons in node.
//------------------------------------------------------------------------------
ulong NODE_TREE_MESH::_count_polygons_in_node(float x_pos, float y_pos, float z_pos,
                                              
float diameter)
{
    
// return if no polygons to process
    if(m_num_polys == 0)
        
return 0;

    
// go through every polygon and keep count of those contained in the specified 3D space.

    
ulong poly_num_in_node = 0;

    
for(ulong i = 0; i < m_num_polys; i++)
    {
        
if(_polygon_contain_in_node(&m_poly_list[i], x_pos, y_pos, z_pos, diameter))
            poly_num_in_node++;
    }

    
return poly_num_in_node;
}

//------------------------------------------------------------------------------
// Adds a node into the list of nodes to draw.
//------------------------------------------------------------------------------
void NODE_TREE_MESH::_add_node(NODE_PTR node)
{
    
if(node == NULL)
        
return;

    
// perform frustum check based on tree type

    
float y_pos;

    
if(m_tree_type == QUADTREE)
        y_pos = 0.0f;
    
else
        y_pos = node->y_pos;

    
float node_radius = node->diameter / 2;
    BOOL  is_completely_contained = FALSE;

    
if(! m_frustum->is_rectangle_in(node->x_pos, y_pos, node->z_pos, 
                                    node_radius, node_radius, node_radius,
                                    &is_completely_contained))
    {
        
return;
    }

    
if(! is_completely_contained)
    {
        
// scan child nodes

        
short num = 0;
        
ulong child_nodes_num = (m_tree_type == QUADTREE) ? 4 : 8;

        
for(ulong i = 0; i < child_nodes_num; i++)
        {
            
if(node->child_nodes[i])
            {
                num++;
                _add_node(node->child_nodes[i]);
            }
        }

        
// do not need to go on if there was child nodes in this node
        if(num != 0)
            
return;
    }

    
// add contained polygons (if any)
    if(node->num_polys != 0)
    {
        
for(ulong i = 0; i < node->num_polys; i++)
        {
            
ulong poly_index = node->poly_index_list[i];

            
// get pointer to polygon
            POLYGON_PTR poly = &m_poly_list[poly_index];

            
// only draw if not done already 
            if(poly->render_timer != m_render_timer)
            {
                poly->render_timer = m_render_timer;

                
// get material group index of polygon
                ulong mg_index = poly->mg_index;

                
// make sure group is okay and material is not transparent
                if(mg_index < m_num_mg && m_root_mesh_info->m_d3d_materials[mg_index].Diffuse.a != 0.0f)
                {
                    
// copy polygon's vertex indices into index buffer
                    *m_mg_list[mg_index].index_ptr++ = poly->vertex_index_0;
                    *m_mg_list[mg_index].index_ptr++ = poly->vertex_index_1;
                    *m_mg_list[mg_index].index_ptr++ = poly->vertex_index_2;

                    
// increase count of polygons to draw in group
                    m_mg_list[mg_index].num_polys_to_draw++;
                }
            }
        }
    }
}

//------------------------------------------------------------------------------
// Constructor, initialize member data.
//------------------------------------------------------------------------------
NODE_TREE_MESH::NODE_TREE_MESH()
{
    memset(
this, 0, sizeof(*this));

    m_tree_type = OCTREE;
}

//------------------------------------------------------------------------------
// Destructor, release allocated memory.
//------------------------------------------------------------------------------
NODE_TREE_MESH::~NODE_TREE_MESH()
{
    free();
}

//------------------------------------------------------------------------------
// Release allocated memory.
//------------------------------------------------------------------------------
void NODE_TREE_MESH::free()
{
    delete m_root_node;
    m_root_node = NULL;

    m_num_polys = 0;
    delete[] m_poly_list;
    m_poly_list = NULL;

    m_num_mg = 0;
    delete[] m_mg_list;
    m_mg_list = NULL;
}

//------------------------------------------------------------------------------
// Create a node-tree mesh from a source MESH object and free old node-tree mesh, 
// specifying the maximum number of polygons in an area than the specific size 
// which forcing node splits.
//------------------------------------------------------------------------------
BOOL NODE_TREE_MESH::create(MESH_PTR mesh,
                            
int tree_type, float node_max_diameter, long max_polys_per_node)
{
    
// free a prior mesh
    free();

    
// error checking    
    if(g_d3d_device == NULL || mesh == NULL || mesh->get_root_mesh_info()->m_num_materials == 0)
        
return FALSE;

    
// get mesh information

    m_root_mesh_info = mesh->get_root_mesh_info();
    ID3DXMesh* d3d_mesh = m_root_mesh_info->m_d3d_mesh;

    m_vertex_fvf           = d3d_mesh->GetFVF();
    m_num_bytes_per_vertex = D3DXGetFVFVertexSize(m_vertex_fvf);
    m_num_polys            = d3d_mesh->GetNumFaces();
    m_max_polys_per_node   = max_polys_per_node;

    
// create the polygon list and group
    m_poly_list = new POLYGON[m_num_polys];
    m_num_mg    = m_root_mesh_info->m_num_materials;
    m_mg_list   = 
new MATERIAL_GROUP[m_num_mg];

    ushort_ptr  index_ptr;
    ulong_ptr   attr_list;

    
// lock the index and attribute buffers
    d3d_mesh->LockIndexBuffer(D3DLOCK_READONLY, (void**)&index_ptr);
    d3d_mesh->LockAttributeBuffer(D3DLOCK_READONLY, &attr_list);

    
// load polygon information into structures
    for(ulong i = 0; i < m_num_polys; i++)
    {
        
ulong mg_index = attr_list[i];  // material group index

        m_poly_list[i].vertex_index_0 = *index_ptr++;
        m_poly_list[i].vertex_index_1 = *index_ptr++;
        m_poly_list[i].vertex_index_2 = *index_ptr++;
        m_poly_list[i].mg_index       = mg_index;
        m_poly_list[i].render_timer   = 0;
                
        m_mg_list[mg_index].num_polys++;
    }

    
// unlock buffers
    d3d_mesh->UnlockAttributeBuffer();
    d3d_mesh->UnlockIndexBuffer();

    
// build the group vertex index buffers
    for(ulong i = 0; i < m_num_mg; i++)
    {
        
if(m_mg_list[i].num_polys != 0)
        {
            UINT index_buffer_length = m_mg_list[i].num_polys * 3 * 
sizeof(ushort);

            g_d3d_device->CreateIndexBuffer(index_buffer_length, D3DUSAGE_WRITEONLY,
                D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_mg_list[i].index_buffer, NULL);
        }
    }

    
// get the size of the bounding cube

    
float bound_max_x, bound_max_y, bound_max_z;

    bound_max_x = (
float) max(fabs(m_root_mesh_info->m_bound_min.x), fabs(m_root_mesh_info->m_bound_max.x));
    bound_max_y = (
float) max(fabs(m_root_mesh_info->m_bound_min.y), fabs(m_root_mesh_info->m_bound_max.y));
    bound_max_z = (
float) max(fabs(m_root_mesh_info->m_bound_min.z), fabs(m_root_mesh_info->m_bound_max.z));

    m_world_cube_diameter = max(bound_max_x, max(bound_max_y, bound_max_z)) * 2.0f;
    m_node_max_diameter   = node_max_diameter;

    
// create the root node
    m_root_node = new NODE;

    
// sort polygons into nodes

    d3d_mesh->LockVertexBuffer(D3DLOCK_READONLY, (
void**)&m_vertex_ptr);

    _sort_node(m_root_node, 0.0f, 0.0f, 0.0f, m_world_cube_diameter);

    d3d_mesh->UnlockVertexBuffer();

    m_render_timer = 0;

    
return TRUE;
}

//------------------------------------------------------------------------------
// Render the current view using view transformation and overloaded distance of view.
// Also specify to use a pre-calculate frustum or force a calculation of own frustum.
//------------------------------------------------------------------------------
BOOL NODE_TREE_MESH::render(FRUSTUM_PTR frustum, float z_dist)
{
    
// error checking
    if(g_d3d_device == NULL || m_root_node == NULL || m_num_polys == 0)
        
return FALSE;

    
// construct the viewing frustum (if none passed)
    if((m_frustum = frustum) == NULL)
    {
        FRUSTUM view_frustum;  
// local viewing frustumn
        view_frustum.create(z_dist);

        m_frustum = &view_frustum;
    }

    D3DXMATRIX matrix;   
// matrix used for calculations

    // set the world transformation matrix to identity,
    // so that level mesh is rendered around the origin it was disigned.
    D3DXMatrixIdentity(&matrix);
    g_d3d_device->SetTransform(D3DTS_WORLD, &matrix);

    
// lock material group index buffer
    for(ulong i = 0; i < m_num_mg; i++)
    {
        
if(m_mg_list[i].num_polys != 0)
        {
            UINT total_vert_index_size = m_mg_list[i].num_polys * 3 * 
sizeof(ushort);

            m_mg_list[i].index_buffer->Lock(0, total_vert_index_size, (
void**) &m_mg_list[i].index_ptr, 0);
        }       

        m_mg_list[i].num_polys_to_draw = 0;
    }

    
// increase render frame timer
    m_render_timer++;

    
// add polygons to be drawn into material group list
    _add_node(m_root_node);

    IDirect3DVertexBuffer9* vertex_buffer = NULL;

    
// get vertex buffer pointer
    m_root_mesh_info->m_d3d_mesh->GetVertexBuffer(&vertex_buffer);

    
// set vertex shader and source
    g_d3d_device->SetStreamSource(0, vertex_buffer, 0, m_num_bytes_per_vertex);
    g_d3d_device->SetFVF(m_vertex_fvf);  

    UINT num_vertices = m_root_mesh_info->m_d3d_mesh->GetNumVertices();

    
// unlock vertex buffers and draw
    for(ulong i = 0; i < m_num_mg; i++)
    {
        
if(m_mg_list[i].num_polys != 0)
            m_mg_list[i].index_buffer->Unlock();

        
if(m_mg_list[i].num_polys_to_draw != 0)
        {
            UINT num_polys_to_draw = m_mg_list[i].num_polys_to_draw;

            g_d3d_device->SetMaterial(&m_root_mesh_info->m_d3d_materials[i]);
            g_d3d_device->SetTexture(0, m_root_mesh_info->m_d3d_textures[i]);
            g_d3d_device->SetIndices(m_mg_list[i].index_buffer);
            g_d3d_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, num_vertices, 0, num_polys_to_draw);
        }
    }

    
// release vertex buffer
    if(vertex_buffer)
        vertex_buffer->Release();

    
return TRUE;
}

//------------------------------------------------------------------------------
// Get closest height above or below point.
//------------------------------------------------------------------------------
float NODE_TREE_MESH::closest_height_between_object_and_mesh(float x_pos, float y_pos, float z_pos)
{
    
return ::closest_height_between_object_and_mesh(m_root_mesh_info->m_d3d_mesh, x_pos, y_pos, z_pos);
}

//------------------------------------------------------------------------------
// Get closest height below point.
//------------------------------------------------------------------------------
float NODE_TREE_MESH::closest_height_below_object(float x_pos, float y_pos, float z_pos)
{
    
return ::closest_height_below_object(m_root_mesh_info->m_d3d_mesh, x_pos, y_pos, z_pos);
}

//------------------------------------------------------------------------------
// Get closest height above point.
//------------------------------------------------------------------------------
float NODE_TREE_MESH::closest_height_above_object(float x_pos, float y_pos, float z_pos)
{
    
return ::closest_height_above_object(m_root_mesh_info->m_d3d_mesh, x_pos, y_pos, z_pos);
}

//------------------------------------------------------------------------------
// Check if a polygon blocks path from start to end.
//------------------------------------------------------------------------------
BOOL NODE_TREE_MESH::is_ray_intersect_mesh(float x_start, float y_start, float z_start,
                                     
float x_end, float y_end, float z_end,
                                     
float* distance)
{
    
return ::is_ray_intersect_mesh(m_root_mesh_info->m_d3d_mesh, 
                                   x_start, y_start, z_start,
                                   x_end, y_end, z_end,
                                   distance);
}
 

posted on 2007-10-25 14:41 lovedday 閱讀(353) 評論(0)  編輯 收藏 引用

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美成人一区二区在线电影 | 亚洲国产另类久久久精品极度| 亚洲日本中文字幕区| 亚洲综合色激情五月| 香蕉尹人综合在线观看| 国产欧美日韩视频一区二区| 午夜久久影院| 欧美国产日韩一区二区三区| 一区二区三区精品在线| 国产精品羞羞答答| 亚洲乱码国产乱码精品精| 欧美视频一区二区三区在线观看| 亚洲色图综合久久| 欧美aⅴ99久久黑人专区| 亚洲毛片网站| 国产一区二区三区精品欧美日韩一区二区三区 | 你懂的国产精品永久在线| 欧美大片在线看免费观看| 性欧美1819性猛交| 蜜桃伊人久久| 性久久久久久久久| 蜜桃精品一区二区三区| 亚洲精品在线三区| 欧美怡红院视频一区二区三区| 亚洲福利在线观看| 午夜精品一区二区三区电影天堂| 亚洲国产高清一区| 国产欧美日韩视频在线观看| 在线观看不卡| 国产香蕉97碰碰久久人人| 欧美午夜不卡| 国产精品ⅴa在线观看h| 激情综合久久| 激情欧美亚洲| 亚洲午夜精品一区二区三区他趣| 999亚洲国产精| 亚洲日本无吗高清不卡| 亚洲黄色毛片| 久久久久国产精品一区三寸 | 激情欧美国产欧美| 亚洲欧美国产精品va在线观看| 欧美成人影音| 久久大综合网| 久久精品一本| 欧美一区=区| 欧美综合国产精品久久丁香| 欧美精品亚洲精品| 欧美日韩国产在线观看| 欧美日本国产在线| 欧美色图天堂网| 亚洲国产影院| 欧美69视频| 久久精品国产清自在天天线| 国产精品久久久亚洲一区 | 亚洲影音一区| 亚洲国产高清自拍| 久久网站热最新地址| 久久精品欧美日韩| 美女视频黄免费的久久| 亚洲欧美在线一区| 噜噜噜91成人网| 欧美电影免费观看| 欧美日韩在线第一页| 欧美日韩直播| 亚洲天堂成人在线观看| 亚洲欧美日韩国产中文| 亚洲精品欧美专区| 欧美日韩激情网| 亚洲一区二区精品| 亚洲线精品一区二区三区八戒| 欧美一级播放| 国产一区二区三区在线观看网站| 久久国产精品72免费观看| 欧美大胆a视频| 欧美成va人片在线观看| 亚洲免费高清| 在线综合亚洲欧美在线视频| 国产精品性做久久久久久| 欧美专区在线观看一区| 久久久久久久精| 欧美视频不卡中文| 小黄鸭精品aⅴ导航网站入口| 亚洲欧美日韩天堂一区二区| 国产精品无码专区在线观看| 久久精品免费| 欧美高清视频一区二区三区在线观看| 国产精品外国| 美女在线一区二区| 欧美区高清在线| 久久久高清一区二区三区| 欧美成人精品1314www| 亚洲综合欧美| 亚洲伦理在线免费看| 国产精品xxxav免费视频| 久久久久久久国产| 欧美激情偷拍| 久久久久久久网| 欧美日韩三级| 美女黄毛**国产精品啪啪 | 午夜视频在线观看一区二区三区| 狠狠干成人综合网| 欧美在线网址| 免费91麻豆精品国产自产在线观看| 一区二区三区精品| 久久精品免费| 亚洲欧美大片| 欧美国产一区二区在线观看| 久久国产精品第一页| 欧美高清hd18日本| 另类春色校园亚洲| 久久精品国产96久久久香蕉| 亚洲精品日产精品乱码不卡| 亚洲综合久久久久| 99国产精品99久久久久久| 亚洲免费小视频| 久久久午夜电影| 欧美一区二区三区的| 中国成人黄色视屏| 亚洲第一色中文字幕| 噜噜噜噜噜久久久久久91| 欧美日韩你懂的| 亚洲激精日韩激精欧美精品| 免费观看30秒视频久久| 国产乱码精品一区二区三区av| 一本久道久久综合中文字幕| 亚洲精品一区二区三区在线观看| 狠狠做深爱婷婷久久综合一区| 国产精品99久久久久久久久| 日韩视频免费看| 欧美sm视频| 亚洲国产精品久久久久久女王| 欧美国产丝袜视频| 免费欧美在线视频| 在线不卡a资源高清| 欧美一区二区三区啪啪| 欧美一级在线视频| 欧美午夜精品久久久| 亚洲美女精品久久| 欧美日韩在线视频观看| 欧美国产一区二区三区激情无套| 一区二区三区在线高清| 久久精品夜夜夜夜久久| 麻豆精品在线视频| 亚洲国产99精品国自产| 女人香蕉久久**毛片精品| 亚洲福利视频在线| 99热在线精品观看| 欧美人与禽猛交乱配视频| 日韩一区二区精品| 亚洲欧美国产视频| 国产偷国产偷亚洲高清97cao| 午夜精品久久久久久久男人的天堂 | 亚洲中字在线| 欧美在线视频播放| 国产综合精品一区| 一本色道精品久久一区二区三区| 国产精品wwwwww| 亚洲一区二区三区在线视频| 亚洲在线中文字幕| 国产日韩综合| 久久综合狠狠| 欧美专区在线| 亚洲国产欧美精品| 欧美老女人xx| 亚洲欧美综合国产精品一区| 久久久久久网站| 欧美激情一区二区三区全黄 | 亚洲三级免费观看| 欧美一区观看| 亚洲人久久久| 久久综合亚洲社区| 亚洲精品国产精品国自产观看浪潮| 一区二区三区视频在线看| 国产麻豆精品久久一二三| 久久亚洲国产精品一区二区| 久久不射2019中文字幕| 在线观看日韩www视频免费| 国产精品久久77777| 久久久久久久久久久久久久一区| 国产精品久久国产精麻豆99网站| 午夜影视日本亚洲欧洲精品| 美女视频黄a大片欧美| 亚洲视频在线观看免费| 极品少妇一区二区三区精品视频| 欧美精品 国产精品| 久久av一区二区三区漫画| 99国产精品久久久久久久| 亚洲精品一区二区在线观看| 国产精品激情电影| 久久综合婷婷| 午夜在线视频观看日韩17c| 亚洲精品国产精品乱码不99| 久久久久.com| 欧美一级精品大片| 亚洲一区二区三区高清不卡| 亚洲精品一区二区三| 亚洲国产精品精华液2区45| 国产一级久久| 国产精自产拍久久久久久| 欧美日韩亚洲国产精品|