您的位置:首页 > 编程语言

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

2010-11-08 22:38 363 查看
// 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: