Ogre 相关老代码-- 第一部分

// CattonShading.cg
void vs_main(
 
 in float4 pos : POSITION,
 in float4 norm : NORMAL,
 in float2 uv   : TEXCOORD0,
 uniform   float4x4 worldMat,
 uniform   float4x4 viewProjMat,
 uniform   float4   eyePos,
 
 out float4 oPos : POSITION,
 out float4 oColor : COLOR0,
 out float2 oUv    : TEXCOORD0
)
{
 float4 wPos = mul(worldMat, pos);
 oPos = mul(viewProjMat, wPos);
 oUv = uv;
 norm = mul( worldMat, norm );
 float4 dir = eyePos - wPos;
 dir = normalize(dir); 
 float d = dot(norm, dir);
 if (d > 0.66) d = 0.66;
 else if (d > 0.33) d = 0.33;
 else d = 0;
 
 d += 0.2;
 
 oColor = float4(d, d, d, 1); 
 
}

void ps_main(
 in float2 uv : TEXCOORD0,
 in float4 color : COLOR0,
 uniform sampler2D tex : TEXUNIT0,
 out float4 oColor : COLOR0
 ) 
{
 oColor = tex2D( tex, uv ) * color;
}

 

//######################################################################

// CattonShading.material
 
vertex_program CatoonShading_vs cg
{
 source CatoonShading.cg
 profiles vs_3_0
 entry_point vs_main
 default_params
 {
  param_named_auto   worldMat            world_matrix
  param_named_auto   viewProjMat         viewproj_matrix
  param_named_auto   eyePos              camera_position
 } 
}

fragment_program CatoonShading_ps cg
{
 source CatoonShading.cg
 profiles ps_3_0
 entry_point ps_main
 default_params
 {
 }
}

material Ogre/Earring_Catoon
{
 technique
 {
  pass
  {
   ambient 0.7 0.7 0
   diffuse 0.7 0.7 0
   
   vertex_program_ref CatoonShading_vs{}
   fragment_program_ref CatoonShading_ps{}

   texture_unit
   {
    texture spheremap.png
    colour_op_ex add src_texture src_current
    colour_op_multipass_fallback one one
    env_map spherical
   }
  }
 }
}

material Ogre/Skin_Catoon
{
 technique
 {
  pass
  {
   ambient 0.3 0.8 0.3
   vertex_program_ref CatoonShading_vs{}
   fragment_program_ref CatoonShading_ps{}

   texture_unit
   {
    texture GreenSkin.jpg
    tex_address_mode mirror
   }
  }
 }
}

material Ogre/Tusks_Catoon
{
 technique
 {
  pass
  {
   ambient 0.7 0.7 0.6
   vertex_program_ref CatoonShading_vs{}
   fragment_program_ref CatoonShading_ps{}

   texture_unit
   {
    texture tusk.jpg
    scale 0.2 0.2
   }
  }
 }
}

material Ogre/Eyes_Catoon
{
 technique
 {
  pass
  {
   ambient 1 0.4 0.4
   diffuse 1 0.7 0
   emissive 0.3 0.1 0
  }
 }
}

 

//##################################################################

//ssao.material

    ///


    vertex_program Mix_AmbientOcclusion_vs cg
    {
        source 1_Mix_AmbientOcclusion.cg
        profiles vs_2_x vp40 arbvp1
        entry_point Mix_AmbientOcclusion_vs

        default_params
        {
            param_named_auto   wvpMat            worldviewproj_matrix
        }
    }

    fragment_program Mix_AmbientOcclusion_ps cg
    {
        source 1_Mix_AmbientOcclusion.cg
        profiles ps_2_x fp40 arbfp1
        entry_point Mix_AmbientOcclusion_ps

        default_params
        {
             param_named_auto TexSize texture_size 0
        }
    }

    ///

    material Mix_AmbientOcclusion
    {
       technique
       {
           pass
           {
                      //scene_blend add

                ambient  0 0 0
                diffuse  0 0 0
                specular 0 0 0 0
                emissive 0 0 0

                vertex_program_ref Mix_AmbientOcclusion_vs
                {
                }

                fragment_program_ref Mix_AmbientOcclusion_ps
                {
                }

                      texture_unit
                      {
                         texture RttTex_DfShNormal
                         filtering none
                         tex_address_mode clamp
                      }

                      texture_unit
                      {
                         texture RttTex_DfShPosition
                         filtering none
                         tex_address_mode clamp
                      }

                      texture_unit
                      {
                         texture randomnormals.png
                      }

                     
           }
       }

    }
//###############################################################

// 1_Mix_AmbientOcclusion.cg


    /
    // Expand a range-compressed vector

    float3 expand(float3 v)
    {
       return (v - 0.5) * 2;
    }

    // compress a normalized vector
    float3 compress(float3 v)
    {
       return (v * 0.5) + 0.5 ;
    }

 

   
    // connector structures

    struct VIn {
        float4 p    : POSITION;
        float2 uv   : TEXCOORD0;
    };

    struct  VOut {
        float4 p    : POSITION;
        float2 uv   : TEXCOORD0;
    };

 

    /
    // vertex program

    VOut Mix_AmbientOcclusion_vs(     
          VIn IN,
        uniform float4x4 wvpMat
          )
    {
        VOut OUT;
      
          OUT.p = mul(wvpMat, IN.p);
        OUT.uv.xy = IN.uv;

        return OUT;
    }

    //
    // SSAO based on http://www.gamedev.net/reference/programming/features/simpleSSAO/ by José María Méndez, MIT license

 

 

    float3 getPosition(sampler2D g_buffer_pos, in float2 uv)
    {
    return tex2D(g_buffer_pos,uv).xyz;
    }

    float3 getNormal(sampler2D g_buffer_norm, in float2 uv)
    {
       return=tex2D(g_buffer_norm, uv).xyz ;
    }

 

 

    float doAmbientOcclusion(sampler2D g_buffer_pos, float2 tcoord,in float2 uv, in float3 p, in float3 cnorm)
    {
       float g_intensity=128;
       float g_scale=1.0;
       float g_bias=0.0;

    float3 diff = getPosition(g_buffer_pos, tcoord + uv) - p;
    const float3 v = normalize(diff);
    const float d = length(diff)*g_scale;
       return max(0.0,dot(cnorm,v)-g_bias)*(1.0/(1.0+d))*g_intensity;

      
    }

    void Mix_AmbientOcclusion_ps(   VOut IN,
                            uniform float4 TexSize,
                            out float4 colour : COLOR,
                            uniform sampler2D Tex_Norm   : TEXUNIT0,
                            uniform sampler2D Tex_Pos         : TEXUNIT1,
                            uniform sampler2D Tex_Rand      : TEXUNIT2
    )
    {


    const float2 vec[4] = {
                                           float2(1,0),
                                           float2(-1,0),
                                           float2(0,1),
                                           float2(0,-1)
                                        };

       float4 Pos= tex2D(Tex_Pos, IN.uv);
    float3 p = Pos.xyz;
    float3 n = getNormal(Tex_Norm, IN.uv);


    float2 rand = normalize(tex2D(Tex_Rand, TexSize * IN.uv / 64.0).xy * 2.0f - 1.0f) ;

    float ao = 0.0f;
       float g_sample_rad=32.0 ;
    float rad = g_sample_rad/p.z;

 


    int iterations = 4;
    for (int j = 0; j < iterations; ++j)
    {
      float2 coord1 = reflect(vec[j],rand)*rad;
      float2 coord2 = float2(coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707);
    
      ao += doAmbientOcclusion(Tex_Pos, IN.uv,coord1*0.25, p, n);
      ao += doAmbientOcclusion(Tex_Pos, IN.uv,coord2*0.5, p, n);
      ao += doAmbientOcclusion(Tex_Pos, IN.uv,coord1*0.75, p, n);
      ao += doAmbientOcclusion(Tex_Pos, IN.uv,coord2, p, n);
    }
    ao/=(float)iterations*4.0;

      
       ao=1-ao ;


    //Do stuff here with your occlusion value “ao”: modulate ambient lighting, write it to a buffer for later //use, etc.
       colour=float4(ao,ao,ao, 1) ;
    }

 

//#######################################################################

    // WARNING: modified by Jacob 'jacmoe' Moen
    // Ported to Ogre3D
    /* * * * * * * * * * * * * Author's note * * * * * * * * * * * */
    *   _       _   _       _   _       _   _       _     _ _ _ _   *
    *  |_|     |_| |_|     |_| |_|_   _|_| |_|     |_|  _|_|_|_|_|  *
    *  |_|_ _ _|_| |_|     |_| |_|_|_|_|_| |_|     |_| |_|_ _ _     *
    *  |_|_|_|_|_| |_|     |_| |_| |_| |_| |_|     |_|   |_|_|_|_   *
    *  |_|     |_| |_|_ _ _|_| |_|     |_| |_|_ _ _|_|  _ _ _ _|_|  *
    *  |_|     |_|   |_|_|_|   |_|     |_|   |_|_|_|   |_|_|_|_|    *
    *                                                               *
    *                     http://www.humus.name                     *
    *                                                                *
    * This file is a part of the work done by Humus. You are free to   *
    * use the code in any way you like, modified, unmodified or copied   *
    * into your own work. However, I expect you to respect these points:  *
    *  - If you use this file and its contents unmodified, or use a major *
    *    part of this file, please credit the author and leave this note. *
    *  - For use in anything commercial, please request my approval.     *
    *  - Share your work and ideas too as much as you can.             *
    *                                                                *
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    #ifndef _BSP_H_
    #define _BSP_H_

    #include "Ogre.h"

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <float.h>
    #include <stddef.h>

    #if _MSC_VER >= 1400
    // To make MSVC 2005 happy
    #pragma warning (disable: 4996)
    #  define assume(x) __assume(x)
    #  define no_alias __declspec(noalias)
    #else
    #  define assume(x)
    #  define no_alias
    #endif

    // Define some sized types
    typedef unsigned char uint8;
    typedef   signed char  int8;

    typedef unsigned short uint16;
    typedef   signed short  int16;

    typedef unsigned int uint32;
    typedef   signed int  int32;

    #ifdef _WIN32
       typedef   signed __int64  int64;
       typedef unsigned __int64 uint64;
    #else
       typedef   signed long long  int64;
       typedef unsigned long long uint64;
    #endif

    typedef unsigned char ubyte;
    typedef unsigned short ushort;
    typedef unsigned int uint;

    template <class TYPE>
    class Array {
    public:
       Array(){
          count = capacity = 0;
          list = NULL;
       }

       Array(const unsigned int iCapasity){
          count = 0;
          capacity = iCapasity;
          list = (TYPE *) malloc(capacity * sizeof(TYPE));
       }
      
       ~Array(){
          free(list);
       }

       TYPE *getArray() const { return list; }
       TYPE *abandonArray(){
          TYPE *rList = list;
          list = NULL;
          return rList;
       }

       TYPE &operator [] (const unsigned int index) const { return list[index]; }
       unsigned int getCount() const { return count; }

       void setCount(const unsigned int newCount){
          capacity = count = newCount;
          list = (TYPE *) realloc(list, capacity * sizeof(TYPE));
       }

       unsigned int add(const TYPE object){
          if (count >= capacity){
             if (capacity) capacity += capacity; else capacity = 8;
             list = (TYPE *) realloc(list, capacity * sizeof(TYPE));
          }
          list[count] = object;
          return count++;
       }

       void fastRemove(const unsigned int index){
          if (index < count){
             count--;
             list[index] = list[count];
          }
       }

       void orderedRemove(const unsigned int index){
          if (index < count){
             count--;
             memmove(list + index, list + index + 1, (count - index) * sizeof(TYPE));
          }
       }

       void clear(){
          count = 0;
       }

       void reset(){
          free(list);
          list = NULL;
          count = capacity = 0;
       }

    private:
       int partition(int (*compare)(const TYPE &elem0, const TYPE &elem1), int p, int r){
          TYPE tmp, pivot = list[p];
          int left = p;

          for (int i = p + 1; i <= r; i++){
             if (compare(list[i], pivot) < 0){
                left++;
                tmp = list[i];
                list[i] = list[left];
                list[left] = tmp;
             }
          }
          tmp = list[p];
          list[p] = list[left];
          list[left] = tmp;
          return left;
       }

       void quickSort(int (*compare)(const TYPE &elem0, const TYPE &elem1), int p, int r){
          if (p < r){
             int q = partition(compare, p, r);
             quickSort(compare, p, q - 1);
             quickSort(compare, q + 1, r);
          }
       }
    public:
       void sort(int (*compare)(const TYPE &elem0, const TYPE &elem1)){
          quickSort(compare, 0, count - 1);
       }
    protected:
       unsigned int capacity;
       unsigned int count;
       TYPE *list;
    };

    struct BTri {
       void split(BTri *dest, int &nPos, int &nNeg, const Ogre::Vector4 &plane, const float epsilon) const;
       void finalize();

       bool intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1) const;

       bool isAbove(const Ogre::Vector3 &pos) const;
 
       float getDistance(const Ogre::Vector3 &pos) const;

       Ogre::Vector4 plane;
       Ogre::Vector4 edgePlanes[3];

       Ogre::Vector3 v[3];
    /*
       Ogre::Vector3 edgeNormals[3];
       float edgeOffsets[3];
       Ogre::Vector3 normal;
       float offset;
    */
       void *data;
    };

    struct BNode {
       ~BNode();

       bool intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector3 &dir, Ogre::Vector3 *point, const BTri **triangle) const;
       BTri *intersectsCached(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector3 &dir) const;
 

    bool pushSphere(Ogre::Vector3 &pos, const float radius) const;
       void getDistance(const Ogre::Vector3 &pos, float &minDist) const;

       void build(Array <BTri> &tris, const int splitCost, const int balCost, const float epsilon);
       //void build(Array <BTri> &tris);

       void read(FILE *file);
       void write(FILE *file) const;

      
       BNode *back;
       BNode *front;

       BTri tri;
    };

 

    class BSP {
    public:
       BSP(){
          top = NULL;
 
          cache = NULL;
       }
       ~BSP(){
 
          delete top;
       }

       void addTriangle(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector3 &v2, void *data = NULL);
       void build(const int splitCost = 3, const int balCost = 1, const float epsilon = 0.001f);

       bool intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, Ogre::Vector3 *point = NULL, const BTri **triangle = NULL) const;
       bool intersectsCached(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1);
 

       bool pushSphere(Ogre::Vector3 &pos, const float radius) const;
       float getDistance(const Ogre::Vector3 &pos) const;

       bool isInOpenSpace(const Ogre::Vector3 &pos) const;
   
       bool loadFile(const char *fileName);
       bool saveFile(const char *fileName) const;

    protected:
       Array <BTri> tris;
       BNode *top;
       BTri *cache;
    };

    #endif // _BSP_H_

 

//###########################################################################

    // WARNING: modified by Jacob 'jacmoe' Moen
    // Ported to Ogre3D
    /* * * * * * * * * * * * * Author's note * * * * * * * * * * * */
    *   _       _   _       _   _       _   _       _     _ _ _ _   *
    *  |_|     |_| |_|     |_| |_|_   _|_| |_|     |_|  _|_|_|_|_|  *
    *  |_|_ _ _|_| |_|     |_| |_|_|_|_|_| |_|     |_| |_|_ _ _     *
    *  |_|_|_|_|_| |_|     |_| |_| |_| |_| |_|     |_|   |_|_|_|_   *
    *  |_|     |_| |_|_ _ _|_| |_|     |_| |_|_ _ _|_|  _ _ _ _|_|  *
    *  |_|     |_|   |_|_|_|   |_|     |_|   |_|_|_|   |_|_|_|_|    *
    *                                                               *
    *                     http://www.humus.name                     *
    *                                                                *
    * This file is a part of the work done by Humus. You are free to   *
    * use the code in any way you like, modified, unmodified or copied   *
    * into your own work. However, I expect you to respect these points:  *
    *  - If you use this file and its contents unmodified, or use a major *
    *    part of this file, please credit the author and leave this note. *
    *  - For use in anything commercial, please request my approval.     *
    *  - Share your work and ideas too as much as you can.             *
    *                                                                *
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    #include "BSP.h"

    #ifdef _WIN32
    #pragma warning(push, 1)
    #pragma warning(disable: 4799)
    #endif

    float planeDistance(const Ogre::Vector3 &normal, const float offset, const Ogre::Vector3 &point){
        return point.x * normal.x + point.y * normal.y + point.z * normal.z + offset;
    }

    float planeDistance(const Ogre::Vector4 &plane, const Ogre::Vector3 &point){
        return point.x * plane.x + point.y * plane.y + point.z * plane.z + plane.w;
    }

    float dot(const Ogre::Vector3 &u, const Ogre::Vector3 &v){
       return u.x * v.x + u.y * v.y + u.z * v.z;
    }

    float dot(const Ogre::Vector4 &u, const Ogre::Vector4 &v){
       return u.x * v.x + u.y * v.y + u.z * v.z + u.w * v.w;
    }
    //#  define no_alias

    no_alias Ogre::Vector3 planeHit(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector4 &plane){
       Ogre::Vector3 dir = v1 - v0;
       float d = planeDistance(plane, v0);
       Ogre::Vector3 pos = v0 - (d / dot((Ogre::Vector3 &) plane, dir)) * dir;

       return pos;
    }

    void BTri::split(BTri *dest, int &nPos, int &nNeg, const Ogre::Vector4 &plane, const float epsilon) const {
       float d[3];
       for (int i = 0; i < 3; i++){
          d[i] = planeDistance(plane, v[i]);
       }

       int first  = 2;
       int second = 0;
       while (!(d[second] > epsilon && d[first] <= epsilon)){
          first = second;
          second++;
       }

       // Positive triangles
       nPos = 0;
       Ogre::Vector3 h = planeHit(v[first], v[second], plane);
       do {
          first = second;
          second++;
          if (second >= 3) second = 0;

          dest->v[0] = h;
          dest->v[1] = v[first];
          if (d[second] > epsilon){
             dest->v[2] = v[second];
          } else {
             dest->v[2] = h = planeHit(v[first], v[second], plane);
          }

          dest->data = data;
          dest->finalize();
          dest++;
          nPos++;
       } while (d[second] > epsilon);

       // Skip zero area triangle
       if (fabsf(d[second]) <= epsilon){
          first = second;
          second++;
          if (second >= 3) second = 0;
       }

       // Negative triangles
       nNeg = 0;
       do {
          first = second;
          second++;
          if (second >= 3) second = 0;

          dest->v[0] = h;
          dest->v[1] = v[first];
          if (d[second] < -epsilon){
             dest->v[2] = v[second];
          } else {
             dest->v[2] = planeHit(v[first], v[second], plane);
          }

          dest->data = data;
          dest->finalize();
          dest++;
          nNeg++;
       } while (d[second] < -epsilon);
    }

    Ogre::Vector3 normalize(const Ogre::Vector3 &v){
       float invLen = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
       return v * invLen;
    }

    Ogre::Vector4 normalize(const Ogre::Vector4 &v){
       float invLen = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
       return v * invLen;
    }

    Ogre::Vector3 cross(const Ogre::Vector3 &u, const Ogre::Vector3 &v){
       return Ogre::Vector3(u.y * v.z - v.y * u.z, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x);
    }

    void BTri::finalize(){
       Ogre::Vector3 normal = normalize(cross(v[1] - v[0], v[2] - v[0]));
       float offset = -dot(v[0], normal);

        Ogre::Vector3 edgeNormals[3];
       edgeNormals[0] = cross(normal, v[0] - v[2]);
       edgeNormals[1] = cross(normal, v[1] - v[0]);
       edgeNormals[2] = cross(normal, v[2] - v[1]);

       float edgeOffsets[3];
       edgeOffsets[0] = dot(edgeNormals[0], v[0]);
       edgeOffsets[1] = dot(edgeNormals[1], v[1]);
       edgeOffsets[2] = dot(edgeNormals[2], v[2]);

       plane = Ogre::Vector4(normal.x, normal.y, normal.z, offset);
       edgePlanes[0] = Ogre::Vector4(edgeNormals[0].x, edgeNormals[0].y, edgeNormals[0].z, -edgeOffsets[0]);
       edgePlanes[1] = Ogre::Vector4(edgeNormals[1].x, edgeNormals[1].y, edgeNormals[1].z, -edgeOffsets[1]);
       edgePlanes[2] = Ogre::Vector4(edgeNormals[2].x, edgeNormals[2].y, edgeNormals[2].z, -edgeOffsets[2]);
    }

    no_alias bool BTri::intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1) const {
       Ogre::Vector3 dir = v0 - v1;
    //   float k = (dot(normal, v0) + offset) / dot(normal, dir);
       float k = planeDistance(plane, v0) / dot(Ogre::Vector3(plane.x, plane.y, plane.z), dir);

       if (k < 0 || k > 1) return false;

       Ogre::Vector3 pos = v0 - k * dir;

       for (unsigned int i = 0; i < 3; i++){
          if (planeDistance(edgePlanes[i], pos) < 0){
    //      if (dot(edgeNormals[i], pos) < edgeOffsets[i]){
             return false;
          }
       }
       return true;
    }

    no_alias bool BTri::isAbove(const Ogre::Vector3 &pos) const {
    /*
       return (edgeNormals[0].x * pos.x + edgeNormals[0].y * pos.y + edgeNormals[0].z * pos.z >= edgeOffsets[0] &&
             edgeNormals[1].x * pos.x + edgeNormals[1].y * pos.y + edgeNormals[1].z * pos.z >= edgeOffsets[1] &&
             edgeNormals[2].x * pos.x + edgeNormals[2].y * pos.y + edgeNormals[2].z * pos.z >= edgeOffsets[2]);
    */
    /*
       return (edgePlanes[0].x * pos.x + edgePlanes[0].y * pos.y + edgePlanes[0].z * pos.z >= -edgePlanes[0].w &&
             edgePlanes[1].x * pos.x + edgePlanes[1].y * pos.y + edgePlanes[1].z * pos.z >= -edgePlanes[1].w &&
             edgePlanes[2].x * pos.x + edgePlanes[2].y * pos.y + edgePlanes[2].z * pos.z >= -edgePlanes[2].w);
    */
       return (planeDistance(edgePlanes[0], pos) >= 0 && planeDistance(edgePlanes[1], pos) >= 0 && planeDistance(edgePlanes[2], pos) >= 0);
    }

    no_alias float BTri::getDistance(const Ogre::Vector3 &pos) const {
       int k = 2;
       for (int i = 0; i < 3; i++){
          float d = planeDistance(edgePlanes[i], pos);
          if (d < 0){
             // Project onto the line between the points
             Ogre::Vector3 dir = v[i] - v[k];
             float c = dot(dir, pos - v[k]) / dot(dir, dir);

             Ogre::Vector3 d;
             if (c >= 1){
                d = v[i];
             } else {
                d = v[k];
                if (c > 0) d += c * dir;
             }

                return Ogre::Vector3(pos - d).length();
          }

          k = i;
       }

       return fabsf(planeDistance(plane, pos));
    }


    #ifdef USE_SIMD
    bool BTri::isAbove3DNow(v2sf v0XY, v2sf v0Z1) const {
       for (int i = 0; i < 3; i++){
          v2sf planeXY = ((v2sf *) &edgePlanes[i])[0];
          v2sf planeZD = ((v2sf *) &edgePlanes[i])[1];

          v2sf dotXY = pfmul(planeXY, v0XY);
          v2sf dotZD = pfmul(planeZD, v0Z1);
          v2sf dot = pfacc(dotXY, dotZD);
          dot = pfacc(dot, dot);

          int d = _m_to_int(dot);
          if (d < 0) return false;
       }

       return true;
    }
    #endif

    BNode::~BNode(){
        delete back;
       delete front;
    }

    no_alias bool BNode::intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1,
        const Ogre::Vector3 &dir, Ogre::Vector3 *point, const BTri **triangle) const {
    #if 0
       float d0 = planeDistance(tri.plane, v0);
       float d1 = planeDistance(tri.plane, v1);

       vec3 pos;
       if (d0 > 0){
          if (d1 <= 0){
             pos = v0 - (d0 / dot(tri.plane.xyz(), dir)) * dir;
          }

          if (front != NULL && front->intersects(v0, (d1 <= 0)? pos : v1, dir, point, triangle)) return true;

          if (d1 <= 0){
             if (tri.isAbove(pos)){
                if (point) *point = pos;
                if (triangle) *triangle = &tri;
                return true;
             }
             if (back != NULL && back->intersects(pos, v1, dir, point, triangle)) return true;
          }
       } else {
          if (d1 > 0){
             pos = v0 - (d0 / dot(tri.plane.xyz(), dir)) * dir;
          }

          if (back != NULL && back->intersects(v0, (d1 > 0)? pos : v1, dir, point, triangle)) return true;

          if (d1 > 0){
             if (tri.isAbove(pos)){
                if (point) *point = pos;
                if (triangle) *triangle = &tri;
                return true;
             }
             if (front != NULL && front->intersects(pos, v1, dir, point, triangle)) return true;
          }
       }

    #else
       float d = planeDistance(tri.plane, v0);

       if (d > 0){
          if (front != NULL && front->intersects(v0, v1, dir, point, triangle)) return true;
          if (planeDistance(tri.plane, v1) < 0){
             Ogre::Vector3 pos = v0 - (d / dot(Ogre::Vector3(tri.plane.x,tri.plane.y,tri.plane.z), dir)) * dir;
             if (tri.isAbove(pos)){
                if (point) *point = pos;
                if (triangle) *triangle = &tri;
                return true;
             }
             if (back != NULL && back->intersects(v0, v1, dir, point, triangle)) return true;
          }
       } else {
          if (back != NULL && back->intersects(v0, v1, dir, point, triangle)) return true;
          if (planeDistance(tri.plane, v1) > 0){
             Ogre::Vector3 pos = v0 - (d / dot(Ogre::Vector3(tri.plane.x,tri.plane.y,tri.plane.z), dir)) * dir;
             if (tri.isAbove(pos)){
                if (point) *point = pos;
                if (triangle) *triangle = &tri;
                return true;
             }
             if (front != NULL && front->intersects(v0, v1, dir, point, triangle)) return true;
          }
       }
    #endif

       return false;
    }

    no_alias BTri *BNode::intersectsCached(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector3 &dir) const {
    #if 0
       float d0 = planeDistance(tri.plane, v0);
       float d1 = planeDistance(tri.plane, v1);

       vec3 pos;

       if (d0 > 0){
          if (d1 <= 0){
             pos = v0 - (d0 / dot((vec3 &) tri.plane, dir)) * dir;
          }

          if (front != NULL){
             BTri *tri;
             if (d1 <= 0){
                tri = front->intersectsCached(v0, pos, dir);
             } else {
                tri = front->intersectsCached(v0, v1, dir);
             }
             if (tri) return tri;
          }

          if (d1 <= 0){
             if (tri.isAbove(pos)) return (BTri *) &tri;
             if (back != NULL){
                BTri *tri = back->intersectsCached(pos, v1, dir);
                if (tri) return tri;
             }
          }
       } else {
          if (d1 > 0){
             pos = v0 - (d0 / dot((vec3 &) tri.plane, dir)) * dir;
          }
          if (back != NULL){
             BTri *tri;
             if (d1 > 0){
                tri = back->intersectsCached(v0, pos, dir);
             } else {
                tri = back->intersectsCached(v0, v1, dir);
             }
             if (tri) return tri;
          }
          if (d1 > 0){
             if (tri.isAbove(pos)) return (BTri *) &tri;
             if (front != NULL){
                BTri *tri = front->intersectsCached(pos, v1, dir);
                if (tri) return tri;
             }
          }
       }

    #else

       float d = planeDistance(tri.plane, v0);

       if (d > 0){
          if (front != NULL){
             BTri *tri = front->intersectsCached(v0, v1, dir);
             if (tri) return tri;
          }
          if (planeDistance(tri.plane, v1) < 0){
             Ogre::Vector3 pos = v0 - (d / dot(Ogre::Vector3(tri.plane.x,tri.plane.y,tri.plane.z), dir)) * dir;
             if (tri.isAbove(pos)) return (BTri *) &tri;
             if (back != NULL){
                BTri *tri = back->intersectsCached(v0, v1, dir);
                if (tri) return tri;
             }
          }
       } else {
          if (back != NULL){
             BTri *tri = back->intersectsCached(v0, v1, dir);
             if (tri) return tri;
          }
          if (planeDistance(tri.plane, v1) > 0){
             Ogre::Vector3 pos = v0 - (d / dot(Ogre::Vector3(tri.plane.x,tri.plane.y,tri.plane.z), dir)) * dir;
             if (tri.isAbove(pos)) return (BTri *) &tri;
             if (front != NULL){
                BTri *tri = front->intersectsCached(v0, v1, dir);
                if (tri) return tri;
             }
          }
       }
    #endif

       return NULL;
    }

 

    no_alias bool BNode::pushSphere(Ogre::Vector3 &pos, const float radius) const {
       float d = planeDistance(tri.plane, pos);

       bool pushed = false;
       if (fabsf(d) < radius){
          if (tri.isAbove(pos)){
    //         pos += (radius - d) * tri.normal;
             pos += (radius - d) * Ogre::Vector3(tri.plane.x,tri.plane.y,tri.plane.z);
             pushed = true;
          }
       }

       if (front != NULL && d > -radius) pushed |= front->pushSphere(pos, radius);
       if (back  != NULL && d <  radius) pushed |= back ->pushSphere(pos, radius);

       return pushed;
    }

    no_alias void BNode::getDistance(const Ogre::Vector3 &pos, float &minDist) const {
       float d = planeDistance(tri.plane, pos);

       float dist = tri.getDistance(pos);
       if (dist < minDist){
          minDist = dist;
       }
      
       if (back && d < minDist){
          back->getDistance(pos, minDist);     
       }

       if (front && -d < minDist){
          front->getDistance(pos, minDist);
       }
    }

    void BNode::read(FILE *file){
       fread(&tri.v, sizeof(tri.v), 1, file);
       tri.finalize();

       int flags = 0;
       fread(&flags, sizeof(int), 1, file);
       if (flags & 1){
          back = new BNode;
          back->read(file);
       } else back = NULL;
       if (flags & 2){
          front = new BNode;
          front->read(file);
       } else front = NULL;
    }

    void BNode::write(FILE *file) const {
       fwrite(&tri.v, sizeof(tri.v), 1, file);
       int flags = 0;
       if (back) flags |= 1;
       if (front) flags |= 2;
       fwrite(&flags, sizeof(int), 1, file);
       if (back) back->write(file);
       if (front) front->write(file);
    }
    /*
    void BNode::build(Array <BTri> &tris){
       uint index = 0;
       int minScore = 0x7FFFFFFF;
       for (uint i = 0; i < tris.getCount(); i++){
          int score = 0;
          int diff = 0;
          for (uint k = 0; k < tris.getCount(); k++){
             uint neg = 0, pos = 0;
             for (uint j = 0; j < 3; j++){
    //            float dist = dot(tris[k].v[j], tris[i].normal) + tris[i].offset;
                float dist = planeDistance(tris[i].plane, tris[k].v[j]);
                if (dist < 0) neg++; else pos++;
             }
             if (pos){
                if (neg) score += 3; else diff++;
             } else diff--;
          }
          score += abs(diff);
          if (score < minScore){
             minScore = score;
             index = i;
          }
       }
       tri = tris[index];
       tris.fastRemove(index);

       Array <BTri> backTris;
       Array <BTri> frontTris;
       for (uint i = 0; i < tris.getCount(); i++){
          uint neg = 0, pos = 0;
          for (uint j = 0; j < 3; j++){
    //         float dist = dot(tris[i].v[j], tri.normal) + tri.offset;
             float dist = planeDistance(tri.plane, tris[i].v[j]);
                if (dist < 0) neg++; else pos++;
          }
          if (neg) backTris.add(tris[i]);
          if (pos) frontTris.add(tris[i]);
       }
       //tris.clear();

       if (backTris.getCount() > 0){
          back = new BNode;
          back->build(backTris);
       } else back = NULL;

       if (frontTris.getCount() > 0){
          front = new BNode;
          front->build(frontTris);
       } else front = NULL;
    }
    */

    void BNode::build(Array <BTri> &tris, const int splitCost, const int balCost, const float epsilon){
       uint index = 0;
       int minScore = 0x7FFFFFFF;

       for (uint i = 0; i < tris.getCount(); i++){
          int score = 0;
          int diff = 0;
          for (uint k = 0; k < tris.getCount(); k++){
             uint neg = 0, pos = 0;
             for (uint j = 0; j < 3; j++){
                float dist = planeDistance(tris[i].plane, tris[k].v[j]);
                if (dist < -epsilon) neg++; else
                if (dist >  epsilon) pos++;
             }
             if (pos){
                if (neg) score += splitCost; else diff++;
             } else {
                if (neg) diff--; else diff++;
             }
          }
          score += balCost * abs(diff);
          if (score < minScore){
             minScore = score;
             index = i;
          }
       }

       tri = tris[index];
       tris.fastRemove(index);

       Array <BTri> backTris;
       Array <BTri> frontTris;
       for (uint i = 0; i < tris.getCount(); i++){

          uint neg = 0, pos = 0;
          for (uint j = 0; j < 3; j++){
             float dist = planeDistance(tri.plane, tris[i].v[j]);
                if (dist < -epsilon) neg++; else
             if (dist >  epsilon) pos++;
          }

          if (neg){
             if (pos){
                BTri newTris[3];
                int nPos, nNeg;
                tris[i].split(newTris, nPos, nNeg, tri.plane, epsilon);
                for (int i = 0; i < nPos; i++){
                   frontTris.add(newTris[i]);
                }
                for (int i = 0; i < nNeg; i++){
                   backTris.add(newTris[nPos + i]);
                }
             } else {
                backTris.add(tris[i]);
             }
          } else {
             frontTris.add(tris[i]);
          }
       }
       tris.reset();

       if (backTris.getCount() > 0){
          back = new BNode;
          back->build(backTris, splitCost, balCost, epsilon);
       } else back = NULL;

       if (frontTris.getCount() > 0){
          front = new BNode;
          front->build(frontTris, splitCost, balCost, epsilon);
       } else front = NULL;
    }
 
    void BSP::addTriangle(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1, const Ogre::Vector3 &v2, void *data){
       BTri tri;

       tri.v[0] = v0;
       tri.v[1] = v1;
       tri.v[2] = v2;
       tri.data = data;

       tri.finalize();

       tris.add(tri);
    }

    void BSP::build(const int splitCost, const int balCost, const float epsilon){
    //   int nTris = tris.getCount();

       top = new BNode;
    //   top->build(tris);
       top->build(tris, splitCost, balCost, epsilon);
    /*
       SSENode *mem = new SSENode[nTris * 4];

       sseTop = (SSENode *) ((intptr(mem) + 15) & ~intptr(0xF));
       sseDest = sseTop + 1;
       sseTop->build(top, sseDest);

       sseDest = mem;
    */
    }

    no_alias bool BSP::intersects(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1,
        Ogre::Vector3 *point, const BTri **triangle) const {
       if (top != NULL) return top->intersects(v0, v1, v1 - v0, point, triangle);

       return false;
    }

    bool BSP::intersectsCached(const Ogre::Vector3 &v0, const Ogre::Vector3 &v1){
       if (top != NULL){
          if (cache){
             if (cache->intersects(v0, v1)) return true;
          }
          cache = top->intersectsCached(v0, v1, v1 - v0);
          return (cache != NULL);
       }

       return false;
    }
 

    bool BSP::pushSphere(Ogre::Vector3 &pos, const float radius) const {
       if (top != NULL) return top->pushSphere(pos, radius);

       return false;
    }

    no_alias float BSP::getDistance(const Ogre::Vector3 &pos) const {
       float dist = FLT_MAX;

       if (top != NULL) top->getDistance(pos, dist);

       return dist;
    }


    no_alias bool BSP::isInOpenSpace(const Ogre::Vector3 &pos) const {
       if (top != NULL){

          BNode *node = top;
          while (true){
             float d = planeDistance(node->tri.plane, pos);

             if (d > 0){
                if (node->front){
                   node = node->front;
                } else return true;
             } else {
                if (node->back){
                   node = node->back;
                } else return false;
             }
          }
       }

       return false;
    }

 
    bool BSP::loadFile(const char *fileName){
       FILE *file = fopen(fileName, "rb");
       if (file == NULL) return false;

       delete top;

       top = new BNode;
       top->read(file);
       fclose(file);

       return true;
    }

    bool BSP::saveFile(const char *fileName) const {
       if (top == NULL) return false;

       FILE *file = fopen(fileName, "wb");
       if (file == NULL) return false;

       top->write(file);
       fclose(file);

       return true;
    }

    #ifdef _WIN32
    #pragma warning(pop)
    #endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值