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

📄 ivp_compact_ledge.hxx

📁 hl2 source code. Do not use it illegal.
💻 HXX
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.

/********************************************************************************
 *	File:	       	ivp_compact_ledge.hxx	
 *	Description:	compacted ledge representation
 *                      contains: Triangle and Tri_Edge infos
 ********************************************************************************/

#ifndef WIN32
#	pragma interface
#endif

#ifndef _IVP_U_TYPES_INCLUDED
#	include "ivu_types.hxx"
#endif

#ifndef _IVP_VECTOR_INCLUDED
#	include "ivu_vector.hxx"
#endif

class IVP_Compact_Triangle;

class IVP_Compact_Surface;
class IVP_Compact_Ledge;
class IVP_Poly_Point;
class IVP_Compact_Ledgetree_Node;

// aligned point for storing data in the compact ledge,
// based on hesse to enforce alignment of data
class IVP_Compact_Poly_Point : public IVP_U_Float_Hesse {
public:
    IVP_Compact_Poly_Point(IVP_U_Point *ipoint){
	this->set(ipoint);
    }
    void set_client_data( void * cl ){
	((void **)&this->hesse_val)[0] = cl;
    }
    void *get_client_data ( ) const {
	return ((void **)&this->hesse_val)[0];
    }
};

#define IVP_MAX_TRIANGLES_PER_LEDGE 8192

class IVP_Compact_Edge	{
private:
  // for edge navigation
  static int next_table[];
  static int prev_table[];

  // contents
  unsigned int start_point_index:16;		// point index
  signed   int opposite_index:15;		// rel to this // maybe extra array, 3 bits more than tri_index/pierce_index
  unsigned int   is_virtual:1;
public:
    // safety and interface methods (mainly internal usage)
  inline void set_start_point_index(int val) {IVP_ASSERT(val>=0 && val< (1<<16)); start_point_index=val; }
  inline void set_opposite_index(int val) {IVP_ASSERT(val>=-(1<<14)+1 && val< (1<<14)-1); opposite_index=val; }
  inline void set_is_virtual(unsigned int val){ is_virtual = val; }; 

    // real public 
public:
  inline int get_start_point_index() const { return start_point_index; };
  inline int get_opposite_index() const { return opposite_index; };
  inline int get_is_virtual() const { return is_virtual; }

    // read content
    //inline const IVP_Compact_Poly_Point *get_start_point() const; // SLOW!	see IVP_Compact_Ledge_Solver
    inline const IVP_Compact_Poly_Point *get_start_point(const IVP_Compact_Ledge *c_ledge) const;
    inline const IVP_Compact_Triangle   *get_triangle() const;
    inline int get_edge_index() const;
    
    // navigation
    inline const IVP_Compact_Edge *get_opposite() const;
    inline       IVP_Compact_Edge *get_opposite();
    inline const IVP_Compact_Edge *get_next() const;
    inline       IVP_Compact_Edge *get_next();
    inline const IVP_Compact_Edge *get_prev() const;
    inline       IVP_Compact_Edge *get_prev();
    inline const IVP_Compact_Ledge *get_compact_ledge() const;
    
    // measures
    IVP_Compact_Edge();

	void byte_swap(); // just byte swap this data

};

class IVP_Compact_Triangle	//
{
private:
  // triangle specific info
  unsigned int tri_index:12; // used for upward navigation
  unsigned int pierce_index:12;
  unsigned int material_index:7;
  unsigned int is_virtual:1;
public:
    // three edges
    IVP_Compact_Edge c_three_edges[3];

  // safety functions for creation
  inline void set_tri_index(int val) {IVP_ASSERT(val>=0 && val< (1<<12)); tri_index=val; }
  inline void set_pierce_index(int val) {IVP_ASSERT(val>=0 && val< (1<<12)); pierce_index=val; }
  inline void set_material_index(int val) {IVP_ASSERT(val>=0 && val< (1<<7)); material_index=val; }
  inline void set_is_virtual(unsigned int val){ is_virtual = val; }; 

  inline int get_tri_index() const { return tri_index; }
  inline int get_pierce_index() const { return pierce_index; }
  inline int get_material_index() const { return material_index; }
  inline int get_is_virtual() const { return is_virtual; }

    inline const IVP_Compact_Edge *get_first_edge() const { return &c_three_edges[0]; };
    inline       IVP_Compact_Edge *get_first_edge()       { return &c_three_edges[0]; };

    inline const IVP_Compact_Edge *get_edge(int index) const { return &c_three_edges[index]; };
    inline const IVP_Compact_Ledge *get_compact_ledge() const;
    inline const IVP_Compact_Triangle *get_next_tri() const { return this+1; };
    inline       IVP_Compact_Triangle *get_next_tri()       { return this+1; };
    
    IVP_Compact_Triangle();

	void byte_swap(); // just byte swap this data ( and the owned edge data )
};

#define IVP_COMPACT_BOUNDINGBOX_STEP_SIZE (1.0f / 250.0f )

class IVP_Compact_Ledge {
    // ATTENTION: some functions depend on EXACTLY THIS SIZE AND SHAPE of the structure
    // e.g. end of class must be 16 aligned for triangle address trick.
    // and assert(sizeof(IVP_Compact_Ledge) == 16 == sizeof(IVP_Compact_Triangle))
    friend class IVP_Compact_Ledge_Generator;
    friend class IVP_SurfaceBuilder_Ledge_Soup;
    friend class IVP_SurfaceBuilder_Mopp;
    friend class IVP_GridBuilder_Array;
private:
    int c_point_offset; // byte offset from 'this' to (ledge) point array
    union {
	int ledgetree_node_offset;
	int client_data;	// if indicates a non terminal ledge
    };
    unsigned int has_chilren_flag:2;
    IVP_BOOL is_compact_flag:2;  // if false than compact ledge uses points outside this piece of memory
    unsigned int dummy:4;
    unsigned int size_div_16:24; 
    short n_triangles;
    short for_future_use;

	inline void set_offset_ledge_points(int offset) { 
		IVP_ASSERT( (offset & 15) == 0 );
		c_point_offset=offset; 
	};

    inline void set_size(int size){ IVP_ASSERT( (size > 0) && (size & 0xf) == 0); size_div_16 = size>>4; };
    inline void set_is_compact(IVP_BOOL x){ is_compact_flag = x; };
public:

    void c_ledge_init();	// memclear(this)

    inline const IVP_Compact_Poly_Point *get_point_array() const { return (IVP_Compact_Poly_Point *)(      ((char *)this) + c_point_offset);   };
    inline       IVP_Compact_Poly_Point *get_point_array()       { return (IVP_Compact_Poly_Point *)(      ((char *)this) + c_point_offset);   };

    // triangles are always placed behind the class instance
    inline const IVP_Compact_Triangle *get_first_triangle() const { return (IVP_Compact_Triangle *)(this+1); };
    inline       IVP_Compact_Triangle *get_first_triangle()       { return (IVP_Compact_Triangle *)(this+1); };
    inline IVP_BOOL is_terminal() const { return (IVP_BOOL)(has_chilren_flag == 0); };

    // get corresponding ledge tree node for recursive compace ledges only ( no grids )
    inline const IVP_Compact_Ledgetree_Node *get_ledgetree_node() const { IVP_ASSERT( !is_terminal() ); return ( IVP_Compact_Ledgetree_Node *)( ((char *)this) + ledgetree_node_offset); };
    
    inline int get_n_triangles() const { return n_triangles; };
    
#if defined(LINUX) || defined(SUN) || (defined(__MWERKS__) && defined(__POWERPC__)) || defined(GEKKO)
    inline int get_n_points() const { return  size_div_16 - n_triangles - 1; };
#endif    

    inline int get_size() const { return size_div_16 * 16; };
    inline IVP_BOOL is_compact(){ return (IVP_BOOL)is_compact_flag; }; // returns true if vertex info is included in compact ledge
    inline int get_client_data() const { IVP_ASSERT( is_terminal()); return client_data; };   // see IVP_Surface_Manager_Polygon for user acces
    inline void set_client_data(unsigned int x){ IVP_ASSERT(is_terminal()); if (is_terminal()) client_data = x; };

	void byte_swap(); // just byte swap this data BUT WILL NOT do the point array, as may be external data or shared and so may be byte swapped > 1 times
	void byte_swap_all(IVP_U_BigVector<IVP_Compact_Poly_Point>* pre_swapped_points); // byte_swap, and recurse too all related child data including the point and triangle data
};


/********************************************************************************
 *	Names:	       	IVP_Compact_Ledgetree_Node
 *	Description:	node on a hierarchy tree
 *			if this->offset < 0 -> this is terminal
 *			else:		left branch of subtree: successor node
 *					right branch of node: this + offset
 ********************************************************************************/
#define IVP_CLT_N_DIRECTIONS 3 // valid values: 3 = AABB

class IVP_Compact_Ledgetree_Node {
public:
    
    // ---------
    // Variables
    // ---------
    int offset_right_node; // (if != 0 than children
    int offset_compact_ledge; //(if != 0, pointer to hull that contains all subelements
    IVP_U_Float_Point3 center;	// in object_coords
    IVP_FLOAT radius; // size of sphere
    uchar box_sizes[IVP_CLT_N_DIRECTIONS];
    uchar free_0;
    // -------
    // Methods
    // -------
    const IVP_Compact_Ledge *get_compact_ledge() const {
	IVP_ASSERT(offset_right_node == 0);
	char *base = (char *)this;
	base += this->offset_compact_ledge;
	return (const IVP_Compact_Ledge *)base;
    }

    const IVP_Compact_Ledgetree_Node* left_son() const {
	IVP_ASSERT(offset_right_node);
	return this+1;
    }
    
    const IVP_Compact_Ledgetree_Node* right_son() const {
	IVP_ASSERT(offset_right_node);
	return (IVP_Compact_Ledgetree_Node *)(((char *)this) + this->offset_right_node);
    }

    IVP_BOOL is_terminal() const {
	if (!offset_right_node) return IVP_TRUE;
	else return IVP_FALSE;
    };
    
    const IVP_Compact_Ledge *get_compact_hull() const {
	if (this->offset_compact_ledge) {
	    return (IVP_Compact_Ledge *)(((char *)this) + this->offset_compact_ledge);
	}else{
	    return NULL;
	}
    };

	void byte_swap(); // just byte swap this data
	void byte_swap_all(IVP_U_BigVector<IVP_Compact_Poly_Point>* pre_swapped_points); // byte_swap, and recurse too all related child data

};




////////////////////////////////////////////////////////////////////////////////////
const IVP_Compact_Triangle *IVP_Compact_Edge::get_triangle() const
{
    // mask 4 lowest adress bits to receive triangle
    return (IVP_Compact_Triangle *)(((unsigned int)this) & 0xfffffff0);
}


const IVP_Compact_Ledge *IVP_Compact_Edge::get_compact_ledge() const
{
    const IVP_Compact_Triangle *c_tri = this->get_triangle();
    c_tri -= c_tri->get_tri_index(); // first triangle
    return (IVP_Compact_Ledge *)(((char *)c_tri) - sizeof(IVP_Compact_Ledge));
}


const IVP_Compact_Poly_Point *IVP_Compact_Edge::get_start_point(const IVP_Compact_Ledge *c_ledge) const
{
    IVP_ASSERT(c_ledge == this->get_compact_ledge());
    return &c_ledge->get_point_array()[this->get_start_point_index()];
}



const IVP_Compact_Edge *IVP_Compact_Edge::get_next() const
{
    int idx = (int)(((unsigned int)this) & 0x0c);
    return (IVP_Compact_Edge *)(((char *)this) + ((int *)(((char *)this->next_table)+idx))[0]);
}

int IVP_Compact_Edge::get_edge_index()const{
  int idx = (int((((unsigned int)this) & 0x0c))>>2) - 1;
    return idx;
}

IVP_Compact_Edge *IVP_Compact_Edge::get_next()
{
    int idx = (int)(((unsigned int)this) & 0x0c);
    return (IVP_Compact_Edge *)(((char *)this) + ((int *)(((char *)this->next_table)+idx))[0]);
}

const IVP_Compact_Edge *IVP_Compact_Edge::get_prev() const
{
    int idx = (int)(((unsigned int)this) & 0x0c);
    return (IVP_Compact_Edge *)(((char *)this) + ((int *)(((char *)this->prev_table)+idx))[0]);
}

IVP_Compact_Edge *IVP_Compact_Edge::get_prev() 
{
    int idx = (int)(((unsigned int)this) & 0x0c);
    return (IVP_Compact_Edge *)(((char *)this) + ((int *)(((char *)this->prev_table)+idx))[0]);
}

const IVP_Compact_Edge *IVP_Compact_Edge::get_opposite() const
{
    int idx = opposite_index; // index is relative!
    return (IVP_Compact_Edge *)(this + idx);
}

IVP_Compact_Edge *IVP_Compact_Edge::get_opposite()
{
    int idx = get_opposite_index(); // index is relative!
    return (IVP_Compact_Edge *)(this + idx);
}


const IVP_Compact_Ledge *IVP_Compact_Triangle::get_compact_ledge() const
{
  const IVP_Compact_Triangle *c_tri = this;
    c_tri -= c_tri->get_tri_index(); // first triangle
    return (IVP_Compact_Ledge *)(((char *)c_tri) - sizeof(IVP_Compact_Ledge));
}





⌨️ 快捷键说明

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