Added initial Smoothed Particle Hydrodynamics implementation (SPH), for CPU and CUDA.

This software is contributed under the ZLib license by Rama Hoetzlein, http://www.rchoetzlein.com
We plan to integrate the SPH into the core Bullet library, including interaction with rigid bodies and soft bodies.
This commit is contained in:
erwin.coumans
2009-05-13 22:28:03 +00:00
parent 4616b62686
commit e260bcd1b2
50 changed files with 61309 additions and 0 deletions

35
Extras/sph/READ_ME.txt Normal file
View File

@@ -0,0 +1,35 @@
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
A fast CPU and GPU fluid simulator. See website above for details.
Notes
(April 2009)
-------------------
- Press 'h' for help screen. This shows keyboard cmds available.
- By default, GPU simulation is off.
When running the fluid_gpu.exe, press 'g' to start/stop GPU simulation.
- Disabling shadows in common_defs.h will greatly speed up the simulation
(You can also press 's' to render without shadows)
- As of April 2009, CUDA builds only under Visual Studio 2005, not VS 2008.
To enable the CUDA build in VS2005, set the BUILD_CUDA define in common_defs.h
Be sure this is turned off if you build with VS2008.
- The GPU integrator is not yet complete. Integration always takes place on the CPU, in both CPU and GPU modes. (As a result, this forces a bus transfer to and from the GPU per cycle. Once the integrator is finished, GPU simulation performance should increase significantly.)
- Occassionally, the GPU simulation with crash cuda, causing the screen to blink and particles to move randomly. This is believed to be due to a not-yet-found out of bounds condition.
ZLib License
-------------------
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

5
Extras/sph/cmp.sh Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
g++ -O3 -L./common -I./common -L./particles -I./particles -lGL -lglut common/matrix.cpp common/mdebug.cpp common/merror.cpp common/vector.cpp common/mtime.cpp particles/particle.cpp particles/particle_system.cpp GLee.c main.cpp
g++ -g -L./common -I./common -L./particles -I./particles -lGL -lglut common/matrix.cpp common/mdebug.cpp common/merror.cpp common/vector.cpp common/mtime.cpp particles/particle.cpp particles/particle_system.cpp GLee.c main.cpp -o sph_sim.debug

17647
Extras/sph/common/GL/GLee.h Normal file

File diff suppressed because it is too large Load Diff

18170
Extras/sph/common/GLee.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef COMMON_DEF
#define COMMON_DEF
// Global defs
//#define USE_SHADOWS // Disable if you don't have FBOs, or to greatly speed up demo.
// #define USE_JPEG
#define BUILD_CUDA // CUDA - Visual Studio 2005 only (as of April 2009)
#define TEX_SIZE 2048
#define LIGHT_NEAR 0.5
#define LIGHT_FAR 300.0
#define DEGtoRAD (3.141592/180.0)
#ifdef _MSC_VER
#include <windows.h>
#else
typedef unsigned int DWORD;
#endif
typedef unsigned int uint;
#define COLOR(r,g,b) ( (DWORD(r*255.0f)<<24) | (DWORD(g*255.0f)<<16) | (DWORD(b*255.0f)<<8) )
#define COLORA(r,g,b,a) ( (DWORD(r*255.0f)<<24) | (DWORD(g*255.0f)<<16) | (DWORD(b*255.0f)<<8) | DWORD(a*255.0f) )
#define RED(c) (float((c>>24) & 0xFF)/255.0)
#define GRN(c) (float((c>>16) & 0xFF)/255.0)
#define BLUE(c) (float((c>>8) & 0xFF)/255.0)
#define ALPH(c) (float(c & 0xFF)/255.0)
#endif

443
Extras/sph/common/geomx.cpp Normal file
View File

@@ -0,0 +1,443 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <vector.h>
#include "geomx.h"
#include "mdebug.h"
#include <assert.h>
GeomX::GeomX ()
{
mHeap = 0x0;
}
void GeomX::FreeBuffers ()
{
for (int n=0; n < (int) mBuf.size(); n++) {
free ( mBuf[n].data );
mBuf[n].data = 0x0;
}
mBuf.clear ();
if ( mHeap != 0x0 ) free ( mHeap );
mHeap = 0x0;
mHeapNum = 0;
mHeapMax = 0;
}
void GeomX::ResetHeap ()
{
mHeapNum = 0;
mHeapFree = -1;
}
int GeomX::GetSize ()
{
int sum = mHeapNum * sizeof(hval) ;
for (int n=0; n < (int) mBuf.size(); n++)
sum += mBuf[n].size;
sum += (int) mAttribute.size() * sizeof(GeomAttr);
return sum;
}
void GeomX::ClearAttributes ()
{
mAttribute.clear ();
}
int GeomX::CopyBuffer ( uchar bdest, uchar bsrc, GeomX& src )
{
if ( bsrc >= src.GetNumBuf() ) return -1;
if ( bdest >= GetNumBuf() ) {
for (int n=0; n <= bdest - GetNumBuf(); n++ )
AddBuffer ( 0, 0, 0 );
}
if ( mBuf[bdest].data != 0x0 ) {
free ( mBuf[bdest].data );
mBuf[bdest].data = 0x0;
}
GeomBuf* buf = src.GetBuffer( bsrc );
mBuf[bdest].dtype = buf->dtype;
mBuf[bdest].max = buf->max;
mBuf[bdest].num = buf->num;
mBuf[bdest].stride = buf->stride;
mBuf[bdest].size = buf->size;
mBuf[bdest].data = (char*) malloc ( mBuf[bdest].max * mBuf[bdest].stride );
memcpy ( mBuf[bdest].data, buf->data, mBuf[bdest].num * mBuf[bdest].stride );
return bdest;
}
void GeomX::CopyBuffers ( GeomX& src )
{
FreeBuffers ();
for (int n = 0; n < src.GetNumBuf(); n++)
CopyBuffer ( n, n, src );
CopyHeap ( src );
}
void GeomX::CopyHeap ( GeomX& src )
{
hpos num, max, freepos;
hval* src_data = src.GetHeap ( num, max, freepos );
if ( mHeap != 0x0 ) {
free ( mHeap );
mHeap = 0x0;
}
mHeap = (hval*) malloc ( max * sizeof(hval) );
mHeapMax = max;
mHeapNum = num;
mHeapFree = freepos;
memcpy ( mHeap, src_data, mHeapNum * sizeof(hval) );
}
hval* GeomX::GetHeap ( hpos& num, hpos& max, hpos& free )
{
num = mHeapNum;
max = mHeapMax;
free = mHeapFree;
return mHeap;
}
void GeomX::CopyAttributes ( GeomX& src )
{
GeomAttr* attr;
ClearAttributes ();
int a;
for (int n = 0; n < src.GetNumAttr(); n++) {
attr = src.GetAttribute ( n );
a = AddAttribute ( (uchar) attr->buf, attr->name, attr->stride, false );
mAttribute[a].offset = attr->offset;
}
}
void GeomX::AddHeap ( int max )
{
mHeap = (hval*) malloc ( max * sizeof(hval ) );
mHeapMax = max;
mHeapNum = 0;
mHeapFree = -1;
}
int GeomX::AddAttribute ( uchar b, std::string name, ushort stride )
{
return AddAttribute ( b, name, stride, true );
}
int GeomX::AddAttribute ( uchar b, std::string name, ushort stride, bool bExtend )
{
GeomBuf* buf = &mBuf[b];
GeomAttr attr;
attr.buf = b;
attr.name = name;
attr.offset = buf->stride;
attr.stride = stride;
if ( bExtend ) {
int new_stride = buf->stride + attr.stride;
char* new_data = (char*) malloc ( buf->max * new_stride );
char* old_data = buf->data;
for (int n=0; n < buf->num; n++) {
memcpy ( new_data, old_data, buf->stride );
old_data += buf->stride;
new_data += new_stride;
}
free ( buf->data );
buf->data = new_data;
buf->stride = new_stride;
}
mAttribute.push_back ( attr );
return (int) mAttribute.size()-1;
}
int GeomX::GetAttribute ( std::string name )
{
for (int n=0; n < (int) mAttribute.size(); n++) {
if ( mAttribute[n].name.compare ( name ) == 0 )
return n;
}
return -1;
}
int GeomX::GetAttrOffset ( std::string name )
{
for (int n=0; n < (int) mAttribute.size(); n++) {
if ( mAttribute[n].name.compare ( name ) == 0 )
return mAttribute[n].offset;
}
return -1;
}
int GeomX::AddBuffer ( uchar typ, ushort stride, int max )
{
GeomBuf buf;
buf.dtype = typ;
buf.stride = stride;
buf.max = max;
buf.num = 0;
buf.size = 0;
buf.data = (char*) malloc ( buf.max * buf.stride );
mBuf.push_back ( buf );
return (int) mBuf.size()-1;
}
void GeomX::ResetBuffer ( uchar b, int n )
{
mBuf[b].max = n;
if ( mBuf[b].data != 0x0 ) free ( mBuf[b].data );
char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
mBuf[b].data = new_data;
mBuf[b].num = 0;
mBuf[b].size = mBuf[b].num*mBuf[b].stride;
}
char* GeomX::AddElem ( uchar b, href& ndx )
{
if ( mBuf[b].num >= mBuf[b].max ) {
if ( long(mBuf[b].max) * 2 > ELEM_MAX ) {
error.PrintF ( "geom", "Maximum number of elements reached.\n" );
error.Exit ();
}
mBuf[b].max *= 2;
char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride );
free ( mBuf[b].data );
mBuf[b].data = new_data;
}
mBuf[b].num++;
mBuf[b].size += mBuf[b].stride;
ndx = mBuf[b].num-1;
return mBuf[b].data + ndx*mBuf[b].stride;
}
char* GeomX::RandomElem ( uchar b, href& ndx )
{
ndx = mBuf[b].num * rand() / RAND_MAX;
return mBuf[b].data + ndx*mBuf[b].stride;
}
int GeomX::AddElem ( uchar b, char* data )
{
if ( mBuf[b].num >= mBuf[b].max ) {
mBuf[b].max *= 2;
char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride );
free ( mBuf[b].data );
mBuf[b].data = new_data;
}
memcpy ( mBuf[b].data + mBuf[b].num*mBuf[b].stride, data, mBuf[b].stride );
mBuf[b].num++;
mBuf[b].size += mBuf[b].stride;
return mBuf[b].num-1;
}
bool GeomX::DelElem ( uchar b, int n )
{
if ( n >= 0 && n < mBuf[b].num ) {
memcpy ( mBuf[b].data + n*mBuf[b].stride, mBuf[b].data + (mBuf[b].num-1)*mBuf[b].stride, mBuf[b].stride );
mBuf[b].num--;
mBuf[b].size -= mBuf[b].stride;
return true;
}
return false;
}
hpos GeomX::HeapExpand ( ushort size, ushort& ret )
{
mHeapMax *= 2;
if ( mHeapMax > HEAP_MAX ) {
error.PrintF ( "geom", "Geom heap size exceeds range of index.\n" );
error.Exit ();
}
hval* pNewHeap = (hval*) malloc ( mHeapMax * sizeof(hval) );
if ( pNewHeap == 0x0 ) {
error.PrintF ( "geom", "Geom heap out of memory.\n" );
error.Exit ();
}
memcpy ( pNewHeap, mHeap, mHeapNum*sizeof(hval) );
free ( mHeap );
mHeap = pNewHeap;
ret = size;
assert ( mHeapNum >= 0 && mHeapNum < mHeapMax );
return mHeapNum;
}
#define LIST_INIT 4
hpos GeomX::HeapAlloc ( ushort size, ushort& ret )
{
hval* pPrev = 0x0;
hval* pCurr = mHeap + mHeapFree;
hpos pos = -1;
if ( mHeapNum + size < mHeapMax ) {
// Heap not yet full.
pos = mHeapNum;
ret = size;
mHeapNum += size;
} else {
// Heap full, search free space
if ( mHeapFree == -1 ) {
pos = HeapExpand ( size, ret );
mHeapNum += ret;
} else {
while ( *pCurr < size && pCurr != mHeap-1 ) {
pPrev = pCurr;
pCurr = mHeap + * (hpos*) (pCurr + FPOS);
}
if ( pCurr != mHeap-1 ) {
// Found free space.
if ( pPrev == 0x0 ) {
mHeapFree = * (hpos*) (pCurr + FPOS);
assert ( mHeapFree >= -1 );
} else {
* (hpos*) (pPrev+FPOS) = * (hpos*) (pCurr+FPOS);
}
pos = pCurr-mHeap;
ret = *pCurr;
} else {
// Heap full, no free space. Expand heap.
pos = HeapExpand ( size, ret );
mHeapNum += ret;
}
}
}
assert ( pos >= 0 && pos <= mHeapNum );
memset ( mHeap+pos, 0, size*sizeof(hval) );
return pos;
}
void GeomX::HeapAddFree ( hpos pos, int size )
{
// memset ( mHeap+pos, 0xFF, size*sizeof(hval) );
if ( pos < mHeapFree || mHeapFree == -1 ) {
// Lowest position. Insert at head of heap.
* (hpos*) (mHeap+pos) = size;
* (hpos*) (mHeap+pos + FPOS) = mHeapFree;
mHeapFree = pos;
if ( mHeapFree != -1 && *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d\n", pos ); error.Exit (); }
assert ( mHeapFree >= -1 );
} else {
hval* pCurr = mHeap + pos;
hval* pPrev = 0x0;
hval* pNext = mHeap + mHeapFree;
if ( pCurr == pNext ) { // Freeing the first block
mHeapFree = * (hpos*) (pCurr + FPOS);
* (hpos*) (mHeap+mHeapFree + FPOS) = 0xFFFFFFFF;
* (hpos*) (pCurr + FPOS) = 0xFFFFFFFF;
* (hpos*) pCurr = 0xFFFFFFFF;
return;
}
// Find first block greater than new free pos.
while ( pNext < pCurr && pNext != mHeap-1 ) {
pPrev = pNext;
pNext = mHeap + * (hpos*) (pNext + FPOS);
}
int x = 0;
if ( pPrev + *(pPrev) == pCurr ) { // Prev block touches current one (expand previous)
* (hpos*) pPrev += size; // - prev.size = prev.size + curr.size
x=1;
} else if ( pCurr + size == pNext && pNext != mHeap-1 ) { // Curr block touches next one (expand current block)
* (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr
* (hpos*) (pCurr + FPOS) = * (hpos*) (pNext + FPOS); // - curr.next = next.next
* (hpos*) pCurr = size + * (hpos*) pNext; // - curr.size = size + next.size
* (hpos*) (pNext) = 0xFFFFFFFF; // - curr = null
* (hpos*) (pNext + FPOS) = 0xFFFFFFFF; // - curr.next = null
x=2;
} else { // Otherwise (linked list insert)
* (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr
if ( pNext != mHeap-1 )
* (hpos*) (pCurr + FPOS) = pNext - mHeap; // - curr.next = next
else
* (hpos*) (pCurr + FPOS) = 0xFFFFFFFF; // - curr.next = null (no next node)
* (hpos*) pCurr = size; // - curr.size = size
x=3;
}
if ( pCurr !=mHeap-1 && *(hpos*) (pCurr+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pCurr, %d, %d\n", x, pos ); error.Exit (); }
if ( pPrev !=mHeap-1 && *(hpos*) (pPrev+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pPrev, %d, %d\n", x, pos ); error.Exit (); }
if ( pNext !=mHeap-1 && *(hpos*) (pNext+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pNext, %d, %d\n", x, pos ); error.Exit (); }
if ( *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d, %d\n", x, pos ); error.Exit (); }
// -- check for bugs (remove eventually)
pNext = mHeap + mHeapFree;
while ( pNext != mHeap-1 ) {
pPrev = pNext;
pNext = mHeap + * (hpos*) (pNext + FPOS);
if ( pNext < pPrev && pNext != mHeap-1 ) {
error.PrintF ( "geomx", "ERROR: Heap free space out of order. %d, %d\n", x, pos );
error.Exit ();
}
}
//---
}
}
void GeomX::ClearRefs ( hList& list )
{
list.cnt = 0;
list.max = 0;
list.pos = 0;
}
hval GeomX::AddRef ( hval r, hList& list, hval delta )
{
if ( list.max == 0 ) {
list.cnt = 1;
list.pos = HeapAlloc ( LIST_INIT, list.max );
*(mHeap + list.pos) = r+delta;
} else {
if ( list.cnt >= list.max ) {
int siz = list.max;
hpos new_pos = HeapAlloc ( siz+LIST_INIT, list.max ); // Alloc new location
//printf ( "MOVE %d -> %d\n", list.pos, new_pos );
memcpy ( mHeap+new_pos, mHeap+list.pos, list.cnt*sizeof(hval) ); // Copy data to new location
HeapAddFree ( list.pos, siz ); // Free old location
list.pos = new_pos;
}
*(mHeap + list.pos + list.cnt) = r+delta;
list.cnt++;
}
return list.pos;
}

125
Extras/sph/common/geomx.h Normal file
View File

@@ -0,0 +1,125 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_GEOM
#define DEF_GEOM
#include <vector>
#define HEAP_MAX 2147483640 // largest heap size (range of hpos)
#define ELEM_MAX 2147483640 // largest number of elements in a buffer (range of hval)
//#define ELEM_MAX 32768 // largest number of elements in a buffer (range of hval)
#define BUF_UNDEF 255
#define FPOS 2 // free position offsets
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef signed int hpos; // pointers into heap
typedef signed int hval; // values in heap
typedef hval href; // values are typically references
struct hList {
ushort cnt;
ushort max;
hpos pos;
};
class GeomAttr {
public:
GeomAttr() { name = ""; buf = 0; stride = 0; offset = 0; }
std::string name;
ushort buf;
ushort stride;
ushort offset;
};
class GeomBuf {
public:
GeomBuf() { dtype = 0; num = 0; max = 0; stride = 0; data = 0x0; }
uchar dtype;
hval num;
hval max;
long size;
ushort stride;
char* data;
};
class GeomX {
public:
GeomX ();
// virtual objType GetType () { return 'geom'; }
// Basic geometry setup
void FreeBuffers ();
void ClearAttributes ();
void AddHeap ( int max );
int CopyBuffer ( uchar bdest, uchar bsrc, GeomX& src );
void CopyBuffers ( GeomX& src );
void CopyAttributes ( GeomX& src );
void CopyHeap ( GeomX& src );
void ResetBuffer ( uchar b, int n );
void ResetHeap ();
int AddBuffer ( uchar typ, ushort stride, int max );
int AddAttribute ( uchar b, std::string name, ushort stride );
int AddAttribute ( uchar b, std::string name, ushort stride, bool bExtend );
int GetAttribute ( std::string name );
int GetAttrOffset ( std::string name );
int NumElem ( uchar b ) { if ( b==BUF_UNDEF) return 0; else return mBuf[b].num; }
int MaxElem ( uchar b ) { if ( b==BUF_UNDEF) return 0; else return mBuf[b].max; }
int GetStride ( uchar b ) { return mBuf[b].stride; }
char* GetElem ( uchar b, int n ) { return mBuf[b].data + n*mBuf[b].stride; }
char* RandomElem ( uchar b, href& ndx );
char* AddElem ( uchar b, href& pos );
int AddElem ( uchar b, char* data );
bool DelElem ( uchar b, int n );
char* GetStart ( uchar b ) { return mBuf[b].data; }
char* GetEnd ( uchar b ) { return mBuf[b].data + mBuf[b].num*mBuf[b].stride; }
GeomBuf* GetBuffer ( uchar b ) { return &mBuf[b]; }
GeomAttr* GetAttribute ( int n ) { return &mAttribute[n]; }
int GetNumBuf () { return (int) mBuf.size(); }
int GetNumAttr () { return (int) mAttribute.size(); }
hval* GetHeap ( hpos& num, hpos& max, hpos& free );
int GetSize ();
/*int AddRef ( int b, int n, int ref, ushort listpos );
int AddRef ( int b, int n, int ref, bool bUseHeap, ushort listpos, ushort width );*/
void ClearRefs ( hList& list );
hval AddRef ( hval r, hList& list, hval delta );
hpos HeapAlloc ( ushort size, ushort& ret );
hpos HeapExpand ( ushort size, ushort& ret );
void HeapAddFree ( hpos pos, int size );
protected:
std::vector< GeomBuf > mBuf;
std::vector< GeomAttr > mAttribute;
hpos mHeapNum;
hpos mHeapMax;
hpos mHeapFree;
hval* mHeap;
};
#endif

View File

@@ -0,0 +1,402 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "common_defs.h"
#include "gl_helper.h"
#include <math.h>
// Shadow Light
float light_proj[16];
float light_x, light_y, light_z;
float light_tox, light_toy, light_toz;
float light_mfov;
// Fonts
void *font = GLUT_BITMAP_8_BY_13;
void *fonts[] = {GLUT_BITMAP_9_BY_15,
GLUT_BITMAP_TIMES_ROMAN_10,
GLUT_BITMAP_TIMES_ROMAN_24};
// Timing
mint::Time tm_last;
int tm_cnt;
float tm_fps;
GLuint glSphere = 65535;
float glRadius = 0.0;
void setSphereRadius ( float r )
{
if ( glRadius == r ) return;
glRadius = r;
// GL sphere
if ( glSphere != 65535 ) glDeleteLists ( glSphere, 1 );
glSphere = glGenLists ( 1 );
float x, y, z, x1, y1, z1;
glNewList ( glSphere, GL_COMPILE );
glBegin ( GL_TRIANGLE_STRIP );
for ( float tilt=-90; tilt <= 90; tilt += 10.0) {
for ( float ang=0; ang <= 360; ang += 30.0) {
x = sin ( ang*DEGtoRAD) * cos ( tilt*DEGtoRAD );
y = cos ( ang*DEGtoRAD) * cos ( tilt*DEGtoRAD );
z = sin ( tilt*DEGtoRAD ) ;
x1 = sin ( ang*DEGtoRAD) * cos ( (tilt+10.0)*DEGtoRAD ) ;
y1 = cos ( ang*DEGtoRAD) * cos ( (tilt+10.0)*DEGtoRAD ) ;
z1 = sin ( (tilt+10.0)*DEGtoRAD );
glNormal3f ( x, y, z ); glVertex3f ( x*r, y*r, z*r );
glNormal3f ( x1, y1, z1 ); glVertex3f ( x1*r, y1*r, z1*r );
}
}
glEnd ();
glEndList ();
}
void drawSphere ()
{
if ( glRadius == 0.0 ) setSphereRadius ( 1.0 );
glCallList ( glSphere );
}
// Check if there have been any openGL problems
void checkOpenGL ()
{
GLenum errCode = glGetError();
if (errCode != GL_NO_ERROR) {
const GLubyte* errString = gluErrorString(errCode);
fprintf( stderr, "OpenGL error: %s\n", errString );
}
}
void drawText ( int x, int y, char* msg)
{
int len, i;
glRasterPos2f(x, y);
len = (int) strlen(msg);
for (i = 0; i < len; i++)
glutBitmapCharacter(font, msg[i]);
}
void drawGrid ()
{
glColor3f ( 0.3, 0.3, 0.3 );
glBegin ( GL_LINES );
for (float x=-40; x<=40.0; x+=10.0 ) {
glVertex3f ( x, -40.0, 0 );
glVertex3f ( x, 40.0, 0 );
}
for (float y=-40; y<=40.0; y+=10.0 ) {
glVertex3f ( -40.0, y, 0 );
glVertex3f ( 40.0, y, 0 );
}
glEnd ();
}
void measureFPS ()
{
// Measure FPS
mint::Time tm_elaps;
if ( ++tm_cnt > 5 ) {
tm_elaps.SetSystemTime ( ACC_NSEC ); // get current sytem time - accurate to 1 ns
tm_elaps = tm_elaps - tm_last; // get elapsed time from 5 frames ago
tm_fps = 5.0 * 1000.0 / tm_elaps.GetMSec (); // compute fps
tm_cnt = 0; // reset frame counter
tm_last.SetSystemTime ( ACC_NSEC );
}
}
void checkFrameBuffers ()
{
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT: printf ( "FBO complete\n" ); break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: printf ( "FBO format unsupported\n"); break;
default: printf ( "Unknown FBO error\n");
}
}
void disableShadows ()
{
glDisable ( GL_TEXTURE_2D );
glActiveTextureARB( GL_TEXTURE1_ARB );
glBindTexture ( GL_TEXTURE_2D, 0 );
glDisable ( GL_TEXTURE_GEN_S );
glDisable ( GL_TEXTURE_GEN_T );
glDisable ( GL_TEXTURE_GEN_R );
glDisable ( GL_TEXTURE_GEN_Q );
glActiveTextureARB( GL_TEXTURE2_ARB );
glBindTexture ( GL_TEXTURE_2D, 0 );
glDisable ( GL_TEXTURE_GEN_S );
glDisable ( GL_TEXTURE_GEN_T );
glDisable ( GL_TEXTURE_GEN_R );
glDisable ( GL_TEXTURE_GEN_Q );
}
#ifdef USE_SHADOWS
// Materials & Textures
GLuint shadow1_id = 0; // display buffer shadows
GLuint shadow2_id = 0; // display buffer shadows
// Frame buffer
GLuint frameBufferObject = 0; // frame buffer shadows
void createFrameBuffer ()
{
//Generate the frame buffer object
glGenFramebuffersEXT (1, &frameBufferObject);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject); // Turn on frame buffer object
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0);
glDrawBuffer (GL_NONE); // Set Draw & ReadBuffer to none since we're rendering depth only
glReadBuffer (GL_NONE);
checkFrameBuffers (); // Check completeness of frame buffer object (no need for stencil and depth attachement)
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); // Turn off frame buffer object
}
void createShadowTextures ()
{
// Create depth texture maps
glActiveTextureARB( GL_TEXTURE1_ARB );
glGenTextures( 1, &shadow1_id );
glBindTexture ( GL_TEXTURE_2D, shadow1_id );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
//-- sets region outside shadow to 0
//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB );
//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB );
//-- sets region outside shadow to 1 (border edge color)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glActiveTextureARB( GL_TEXTURE2_ARB );
glGenTextures( 1, &shadow2_id );
glBindTexture ( GL_TEXTURE_2D, shadow2_id );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB );
//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
}
void computeLightMatrix ( int n, int tx, int ty )
{
int lnum = n;
// Construct projective texturing matrix
// S - light bias matrix
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ();
glTranslatef ( 0.5, 0.5, 0.5 );
glScalef ( 0.5, 0.5, 0.5 );
// Plight - light projection matrix
gluPerspective ( light_mfov*2.0, float(tx) / ty, LIGHT_NEAR, LIGHT_FAR );
// L^-1 - light view inverse matrix
gluLookAt ( light_x, light_y, light_z, light_tox, light_toy, light_toz, 0, 0, 1);
glPushMatrix ();
glGetFloatv ( GL_MODELVIEW_MATRIX, light_proj );
glPopMatrix ();
}
void renderDepthMap_Clear ( float wx, float wy )
{
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0);
glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage
glViewport (1, 1, TEX_SIZE-2, TEX_SIZE-2); // Note: Avoid artifact cause by drawing into border pixels
glClear ( GL_DEPTH_BUFFER_BIT );
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glViewport ( 0, 0, (GLsizei) wx, (GLsizei) wy );
}
void renderDepthMap_FrameBuffer ( int n, float wx, float wy )
{
float vmat[16];
computeLightMatrix ( n, TEX_SIZE, TEX_SIZE );
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject);
if ( n == 0 ) {
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0);
} else {
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow2_id, 0);
}
if ( n == 0 ) glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage
else glActiveTextureARB( GL_TEXTURE2_ARB ); // TEXTURE2 = shadow map stage
glViewport (1, 1, TEX_SIZE-2, TEX_SIZE-2); // Note: Avoid artifact cause by drawing into border pixels
glClear ( GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
// Plight - projection matrix of light
glMatrixMode ( GL_PROJECTION ); // Setup projection for depth-map rendering
glLoadIdentity ();
gluPerspective ( light_mfov*2.0, float(TEX_SIZE) / TEX_SIZE, LIGHT_NEAR, LIGHT_FAR );
// L^-1 - light view matrix (gluLookAt computes inverse)
glMatrixMode ( GL_MODELVIEW); // Setup view for depth-map rendering
glLoadIdentity ();
gluLookAt ( light_x, light_y, light_z, light_tox, light_toy, light_toz, 0, 0, 1);
glPushMatrix (); // Save view matrix for later
glGetFloatv ( GL_MODELVIEW_MATRIX, vmat );
glPopMatrix ();
glDisable ( GL_LIGHTING );
glColor4f ( 1, 1, 1, 1 );
glShadeModel (GL_FLAT); // No shading (faster)
glEnable ( GL_CULL_FACE );
glCullFace ( GL_FRONT );
glEnable ( GL_POLYGON_OFFSET_FILL );
glPolygonOffset ( 50.0, 0.1 ); // Depth bias
drawScene ( &vmat[0], false ); // Draw scene.
glDisable ( GL_POLYGON_OFFSET_FILL );
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glViewport ( 0, 0, (GLsizei) wx, (GLsizei) wy );
//glCullFace (GL_BACK); // Restore render states
//glBindTexture ( GL_TEXTURE_2D, 0);
}
void renderShadowStage ( int n, float* vmat )
{
GLfloat pos[4];
GLfloat row[4];
computeLightMatrix ( n, TEX_SIZE, TEX_SIZE );
if ( n == 0 ) {
glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage #1
} else {
glActiveTextureARB( GL_TEXTURE2_ARB ); // TEXTURE2 = shadow map stage #2
}
glEnable ( GL_TEXTURE_2D );
if ( n == 0 ) glBindTexture ( GL_TEXTURE_2D, shadow1_id );
else glBindTexture ( GL_TEXTURE_2D, shadow2_id );
glMatrixMode( GL_MODELVIEW );
glLoadMatrixf ( vmat );
row[0] = light_proj[0]; row[1] = light_proj[4]; row[2] = light_proj[8]; row[3] = light_proj[12];
glTexGenfv(GL_S, GL_EYE_PLANE, &row[0] );
row[0] = light_proj[1]; row[1] = light_proj[5]; row[2] = light_proj[9]; row[3] = light_proj[13];
glTexGenfv(GL_T, GL_EYE_PLANE, &row[0] );
row[0] = light_proj[2]; row[1] = light_proj[6]; row[2] = light_proj[10]; row[3] = light_proj[14];
glTexGenfv(GL_R, GL_EYE_PLANE, &row[0] );
row[0] = light_proj[3]; row[1] = light_proj[7]; row[2] = light_proj[11]; row[3] = light_proj[15];
glTexGenfv(GL_Q, GL_EYE_PLANE, &row[0] );
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE ) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS ) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT ) ;
pos[0] = 0.20;
pos[1] = 0.20;
pos[2] = 0.20;
pos[3] = 0.20;
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &pos[0] );
}
void renderShadows ( float* vmat )
{
GLfloat pos[4];
renderShadowStage ( 0, vmat );
// renderShadowStage ( 1, vmat );
glActiveTextureARB( GL_TEXTURE0_ARB ); // Render Tex 0 - Base render
glDisable ( GL_TEXTURE_GEN_S );
glDisable ( GL_TEXTURE_GEN_T );
glDisable ( GL_TEXTURE_GEN_R );
glDisable ( GL_TEXTURE_GEN_Q );
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glEnable ( GL_LIGHTING );
glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT);
glEnable ( GL_LIGHT0 );
pos[0] = light_x; pos[1] = light_y; pos[2] = light_z; pos[3] = 1.0;
glLightfv ( GL_LIGHT0, GL_POSITION, &pos[0] );
/* glEnable ( GL_LIGHT1 );
pos[0] = light[1].x; pos[1] = light[1].y; pos[2] = light[1].z; pos[3] = 1.0;
glLightfv ( GL_LIGHT1, GL_POSITION, &pos[0] );*/
}
void setShadowLight ( float fx, float fy, float fz, float tx, float ty, float tz, float fov )
{
light_x = fx;
light_y = fy;
light_z = fz;
light_tox = tx;
light_toy = ty;
light_toz = tz;
light_mfov = fov;
}
void setShadowLightColor ( float dr, float dg, float db, float sr, float sg, float sb )
{
GLfloat amb[4] = {0.0,0.0,0.0,1};
GLfloat dif[4];
GLfloat spec[4];
GLfloat pos[4] = {0.0,0.0,0.0, 100.0};
glEnable(GL_LIGHT0);
dif[0] = dr; dif[1] = dg; dif[2] = db; dif[3] = 1;
spec[0] = sr; spec[1] = sg; spec[2] = sb; spec[3] = 1;
glLightfv(GL_LIGHT0, GL_AMBIENT, &amb[0] );
glLightfv(GL_LIGHT0, GL_DIFFUSE, &dif[0] );
glLightfv(GL_LIGHT0, GL_SPECULAR, &spec[0] );
}
#endif

View File

@@ -0,0 +1,89 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GL_HELPER
#define GL_HELPER
#include "common_defs.h"
#include <gl/glee.h>
#include <gl/glext.h>
#ifdef _MSC_VER // Windows
#ifdef USE_SHADOWS
#include <gl/glee.h>
#include <gl/glext.h>
#endif
#include <gl/glut.h>
#else // Linux
#ifdef USE_SHADOWS
#include "GLee.h"
#endif
#include <GL/glext.h>
#include <GL/glut.h>
#endif
#include "image.h"
#include "mtime.h"
extern void checkOpenGL ();
extern void drawText ( int x, int y, char* msg);
extern void drawGrid ();
extern void measureFPS ();
extern mint::Time tm_last;
extern int tm_cnt;
extern float tm_fps;
extern void disableShadows ();
extern void checkFrameBuffers ();
extern GLuint glSphere;
extern float glRadius;
extern void setSphereRadius ( float f );
extern void drawSphere ();
#ifdef USE_SHADOWS
extern void setShadowLight ( float fx, float fy, float fz, float tx, float ty, float tz, float fov );
extern void setShadowLightColor ( float dr, float dg, float db, float sr, float sg, float sb );
extern void createFrameBuffer ();
extern void createShadowTextures ();
extern void computeLightMatrix ( int n, int tx, int ty );
extern void renderDepthMap_Clear ( float wx, float wy );
extern void renderDepthMap_FrameBuffer ( int n, float wx, float wy );
extern void renderShadowStage ( int n, float* vmat );
extern void renderShadows ( float* vmat );
extern void drawScene ( float* view_mat, bool bShaders ); // provided by user
extern float light_proj[16];
extern float light_x, light_y, light_z;
extern float light_tox, light_toy, light_toz;
extern float light_mfov;
extern GLuint shadow1_id;
extern GLuint shadow2_id;
#endif
#endif

7139
Extras/sph/common/glext.h Normal file

File diff suppressed because it is too large Load Diff

791
Extras/sph/common/glut.h Normal file
View File

@@ -0,0 +1,791 @@
#ifndef __glut_h__
#define __glut_h__
/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998, 2000, 2006. */
/* This program is freely distributable without licensing fees and is
provided without guarantee or warrantee expressed or implied. This
program is -not- in the public domain. */
#if defined(_WIN32) || defined(__CYGWIN__)
/* GLUT 3.7 now tries to avoid including <windows.h>
to avoid name space pollution, but Win32's <GL/gl.h>
needs APIENTRY and WINGDIAPI defined properly. */
# if 0
/* This would put tons of macros and crap in our clean name space. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# else
/* XXX This is from Win32's <windef.h> */
# ifndef APIENTRY
# define GLUT_APIENTRY_DEFINED
/* Cygwin and MingW32 are two free GNU-based Open Source compilation
environments for Win32. Note that __CYGWIN32__ is deprecated
in favor of simply __CYGWIN__. */
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# if defined(__CYGWIN__)
# define APIENTRY __stdcall
# else
# ifdef i386
# define APIENTRY __attribute__((stdcall))
# else
# define APIENTRY
# endif
# endif
# else
# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
# define APIENTRY __stdcall
# else
# define APIENTRY
# endif
# endif
# endif
/* XXX This is from Win32's <winnt.h> */
# ifndef CALLBACK
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# ifndef __stdcall
# define __stdcall __attribute__((stdcall))
# endif
# define CALLBACK __stdcall
# else
# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
# define CALLBACK __stdcall
# else
# define CALLBACK
# endif
# endif
# endif
/* XXX This is from Win32's <wingdi.h> and <winnt.h> */
# ifndef WINGDIAPI
# define GLUT_WINGDIAPI_DEFINED
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# define WINGDIAPI
# else
# define WINGDIAPI __declspec(dllimport)
# endif
# endif
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
/* Rely on Cygwin32/MingW32 <stddef.h> to set wchar_t. */
/* XXX Warning. The Cygwin32/MingW32 definition for wchar_t
is an "int" instead of the "short" used by Windows. */
# include <stddef.h>
# else
/* XXX This is from Win32's <ctype.h> */
# ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
# define _WCHAR_T_DEFINED
# endif
# endif
# endif
/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA
in your compile preprocessor options (Microsoft Visual C only). */
# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) && defined(_MSC_VER)
# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */
# pragma comment (lib, "user32.lib") /* link with Windows User lib */
# pragma comment (lib, "gdi32.lib") /* link with Windows GDI lib */
/* To enable automatic SGI OpenGL for Windows library usage for GLUT,
define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */
# ifdef GLUT_USE_SGI_OPENGL
# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */
# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */
# if defined(GLUT_STATIC_LIB)
# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
# else
# pragma comment (lib, "glut.lib") /* link with Win32 GLUT lib */
# endif
# else
# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */
# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */
# if defined(GLUT_STATIC_LIB)
# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
# else
# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */
# endif
# endif
# endif
/* To disable supression of annoying warnings about floats being promoted
to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor
options. */
# if defined(_MSC_VER) && !defined(GLUT_NO_WARNING_DISABLE)
# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */
# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */
# endif
/* Win32 has an annoying issue where there are multiple C run-time
libraries (CRTs). If the executable is linked with a different CRT
from the GLUT DLL, the GLUT DLL will not share the same CRT static
data seen by the executable. In particular, atexit callbacks registered
in the executable will not be called if GLUT calls its (different)
exit routine). GLUT is typically built with the
"/MD" option (the CRT with multithreading DLL support), but the Visual
C++ linker default is "/ML" (the single threaded CRT).
One workaround to this issue is requiring users to always link with
the same CRT as GLUT is compiled with. That requires users supply a
non-standard option. GLUT 3.7 has its own built-in workaround where
the executable's "exit" function pointer is covertly passed to GLUT.
GLUT then calls the executable's exit function pointer to ensure that
any "atexit" calls registered by the application are called if GLUT
needs to exit.
Note that the __glut*WithExit routines should NEVER be called directly.
To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
/* XXX This is from Win32's <process.h> */
# if !defined(_MSC_VER) && !defined(__cdecl)
/* Define __cdecl for non-Microsoft compilers. */
# define __cdecl
# define GLUT_DEFINED___CDECL
# endif
# ifndef _CRTIMP
# ifdef _NTSDK
/* Definition compatible with NT SDK */
# define _CRTIMP
# else
/* Current definition */
# ifdef _DLL
# define _CRTIMP __declspec(dllimport)
# else
# define _CRTIMP
# endif
# endif
# define GLUT_DEFINED__CRTIMP
# endif
/* GLUT API entry point declarations for Win32. */
# ifdef GLUT_BUILDING_LIB
/* MSDN article 835326 says "When you build a DLL by using the 64-bit
version of the Microsoft Visual C++ Compiler and Linker, you may
receive Linker error number LNK4197 if a function has been declared
for export more than one time." GLUT builds with glut.def that
declares GLUT's EXPORTS list so do not use __declspec(dllexport)
to keep 64-bit compiler happy. */
# define GLUTAPI /*__declspec(dllexport)*/
# else
# ifdef _DLL
# define GLUTAPI __declspec(dllimport)
# else
# define GLUTAPI extern
# endif
# endif
/* GLUT callback calling convention for Win32. */
# define GLUTCALLBACK __cdecl
# if (_MSC_VER >= 800) || defined(__MINGW32__) || defined(_STDCALL_SUPPORTED) || defined(__CYGWIN32__)
# define GLUTAPIENTRY __stdcall
# else
# define GLUTAPIENTRY
# endif
#endif /* _WIN32 */
#include <GL/gl.h>
#include <GL/glu.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
# ifndef GLUT_BUILDING_LIB
# if __BORLANDC__
# if defined(_BUILDRTLDLL)
void __cdecl __export exit(int __status);
# else
void __cdecl exit(int __status);
# endif
# else
# if _MSC_VER >= 1200
extern _CRTIMP __declspec(noreturn) void __cdecl exit(int);
# else
extern _CRTIMP void __cdecl exit(int);
# endif
# endif
# endif
#else
/* non-Win32 case. */
/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */
# define APIENTRY
# define GLUT_APIENTRY_DEFINED
# define CALLBACK
/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */
# define GLUTAPI extern
# define GLUTAPIENTRY
# define GLUTCALLBACK
/* Prototype exit for the non-Win32 case (see above). */
# ifdef __GNUC__
extern void exit(int __status) __attribute__((__noreturn__));
# else
extern void exit(int);
# endif
#endif
/**
GLUT API revision history:
GLUT_API_VERSION is updated to reflect incompatible GLUT
API changes (interface changes, semantic changes, deletions,
or additions).
GLUT_API_VERSION=1 First public release of GLUT. 11/29/94
GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling,
extension. Supports new input devices like tablet, dial and button
box, and Spaceball. Easy to query OpenGL extensions.
GLUT_API_VERSION=3 glutMenuStatus added.
GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer,
glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic
video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc,
glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat,
glutJoystickFunc, glutForceJoystickFunc, glutStrokeWidthf,
glutStrokeLengthf (NOT FINALIZED!).
**/
#ifndef GLUT_API_VERSION /* allow this to be overriden */
#define GLUT_API_VERSION 3
#endif
/**
GLUT implementation revision history:
GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT
API revisions and implementation revisions (ie, bug fixes).
GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of
GLUT Xlib-based implementation. 11/29/94
GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of
GLUT Xlib-based implementation providing GLUT version 2
interfaces.
GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95
GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95
GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95
GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96
GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner
and video resize. 1/3/97
GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines.
GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release.
GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling.
GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support.
GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface.
GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa <GL/glut.h>
GLUT_XLIB_IMPLEMENTATION=16 mjk's early GLUT 3.8
GLUT_XLIB_IMPLEMENTATION=17 mjk's GLUT 3.8 with glutStrokeWidthf and glutStrokeLengthf
**/
#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */
#define GLUT_XLIB_IMPLEMENTATION 17
#endif
/* Display mode bit masks. */
#define GLUT_RGB 0
#define GLUT_RGBA GLUT_RGB
#define GLUT_INDEX 1
#define GLUT_SINGLE 0
#define GLUT_DOUBLE 2
#define GLUT_ACCUM 4
#define GLUT_ALPHA 8
#define GLUT_DEPTH 16
#define GLUT_STENCIL 32
#if (GLUT_API_VERSION >= 2)
#define GLUT_MULTISAMPLE 128
#define GLUT_STEREO 256
#endif
#if (GLUT_API_VERSION >= 3)
#define GLUT_LUMINANCE 512
#endif
/* Mouse buttons. */
#define GLUT_LEFT_BUTTON 0
#define GLUT_MIDDLE_BUTTON 1
#define GLUT_RIGHT_BUTTON 2
/* Mouse button state. */
#define GLUT_DOWN 0
#define GLUT_UP 1
#if (GLUT_API_VERSION >= 2)
/* function keys */
#define GLUT_KEY_F1 1
#define GLUT_KEY_F2 2
#define GLUT_KEY_F3 3
#define GLUT_KEY_F4 4
#define GLUT_KEY_F5 5
#define GLUT_KEY_F6 6
#define GLUT_KEY_F7 7
#define GLUT_KEY_F8 8
#define GLUT_KEY_F9 9
#define GLUT_KEY_F10 10
#define GLUT_KEY_F11 11
#define GLUT_KEY_F12 12
/* directional keys */
#define GLUT_KEY_LEFT 100
#define GLUT_KEY_UP 101
#define GLUT_KEY_RIGHT 102
#define GLUT_KEY_DOWN 103
#define GLUT_KEY_PAGE_UP 104
#define GLUT_KEY_PAGE_DOWN 105
#define GLUT_KEY_HOME 106
#define GLUT_KEY_END 107
#define GLUT_KEY_INSERT 108
#endif
/* Entry/exit state. */
#define GLUT_LEFT 0
#define GLUT_ENTERED 1
/* Menu usage state. */
#define GLUT_MENU_NOT_IN_USE 0
#define GLUT_MENU_IN_USE 1
/* Visibility state. */
#define GLUT_NOT_VISIBLE 0
#define GLUT_VISIBLE 1
/* Window status state. */
#define GLUT_HIDDEN 0
#define GLUT_FULLY_RETAINED 1
#define GLUT_PARTIALLY_RETAINED 2
#define GLUT_FULLY_COVERED 3
/* Color index component selection values. */
#define GLUT_RED 0
#define GLUT_GREEN 1
#define GLUT_BLUE 2
#ifdef _WIN32
/* Stroke font constants (use these in GLUT program). */
#define GLUT_STROKE_ROMAN ((void*)0)
#define GLUT_STROKE_MONO_ROMAN ((void*)1)
/* Bitmap font constants (use these in GLUT program). */
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)
#if (GLUT_API_VERSION >= 3)
#define GLUT_BITMAP_HELVETICA_10 ((void*)6)
#define GLUT_BITMAP_HELVETICA_12 ((void*)7)
#define GLUT_BITMAP_HELVETICA_18 ((void*)8)
#endif
#else
/* Stroke font opaque addresses (use constants instead in source code). */
GLUTAPI void *glutStrokeRoman;
GLUTAPI void *glutStrokeMonoRoman;
/* Stroke font constants (use these in GLUT program). */
#define GLUT_STROKE_ROMAN (&glutStrokeRoman)
#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman)
/* Bitmap font opaque addresses (use constants instead in source code). */
GLUTAPI void *glutBitmap9By15;
GLUTAPI void *glutBitmap8By13;
GLUTAPI void *glutBitmapTimesRoman10;
GLUTAPI void *glutBitmapTimesRoman24;
GLUTAPI void *glutBitmapHelvetica10;
GLUTAPI void *glutBitmapHelvetica12;
GLUTAPI void *glutBitmapHelvetica18;
/* Bitmap font constants (use these in GLUT program). */
#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15)
#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13)
#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10)
#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24)
#if (GLUT_API_VERSION >= 3)
#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10)
#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12)
#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18)
#endif
#endif
/* glutGet parameters. */
#define GLUT_WINDOW_X ((GLenum) 100)
#define GLUT_WINDOW_Y ((GLenum) 101)
#define GLUT_WINDOW_WIDTH ((GLenum) 102)
#define GLUT_WINDOW_HEIGHT ((GLenum) 103)
#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104)
#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105)
#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106)
#define GLUT_WINDOW_RED_SIZE ((GLenum) 107)
#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108)
#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109)
#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110)
#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111)
#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112)
#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113)
#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114)
#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115)
#define GLUT_WINDOW_RGBA ((GLenum) 116)
#define GLUT_WINDOW_PARENT ((GLenum) 117)
#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118)
#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119)
#if (GLUT_API_VERSION >= 2)
#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120)
#define GLUT_WINDOW_STEREO ((GLenum) 121)
#endif
#if (GLUT_API_VERSION >= 3)
#define GLUT_WINDOW_CURSOR ((GLenum) 122)
#endif
#define GLUT_SCREEN_WIDTH ((GLenum) 200)
#define GLUT_SCREEN_HEIGHT ((GLenum) 201)
#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202)
#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203)
#define GLUT_MENU_NUM_ITEMS ((GLenum) 300)
#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400)
#define GLUT_INIT_WINDOW_X ((GLenum) 500)
#define GLUT_INIT_WINDOW_Y ((GLenum) 501)
#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502)
#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503)
#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504)
#if (GLUT_API_VERSION >= 2)
#define GLUT_ELAPSED_TIME ((GLenum) 700)
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123)
#endif
#if (GLUT_API_VERSION >= 2)
/* glutDeviceGet parameters. */
#define GLUT_HAS_KEYBOARD ((GLenum) 600)
#define GLUT_HAS_MOUSE ((GLenum) 601)
#define GLUT_HAS_SPACEBALL ((GLenum) 602)
#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603)
#define GLUT_HAS_TABLET ((GLenum) 604)
#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605)
#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606)
#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607)
#define GLUT_NUM_DIALS ((GLenum) 608)
#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609)
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610)
#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611)
#define GLUT_HAS_JOYSTICK ((GLenum) 612)
#define GLUT_OWNS_JOYSTICK ((GLenum) 613)
#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614)
#define GLUT_JOYSTICK_AXES ((GLenum) 615)
#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616)
#endif
#if (GLUT_API_VERSION >= 3)
/* glutLayerGet parameters. */
#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800)
#define GLUT_LAYER_IN_USE ((GLenum) 801)
#define GLUT_HAS_OVERLAY ((GLenum) 802)
#define GLUT_TRANSPARENT_INDEX ((GLenum) 803)
#define GLUT_NORMAL_DAMAGED ((GLenum) 804)
#define GLUT_OVERLAY_DAMAGED ((GLenum) 805)
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
/* glutVideoResizeGet parameters. */
#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900)
#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901)
#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902)
#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903)
#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904)
#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905)
#define GLUT_VIDEO_RESIZE_X ((GLenum) 906)
#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907)
#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908)
#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909)
#endif
/* glutUseLayer parameters. */
#define GLUT_NORMAL ((GLenum) 0)
#define GLUT_OVERLAY ((GLenum) 1)
/* glutGetModifiers return mask. */
#define GLUT_ACTIVE_SHIFT 1
#define GLUT_ACTIVE_CTRL 2
#define GLUT_ACTIVE_ALT 4
/* glutSetCursor parameters. */
/* Basic arrows. */
#define GLUT_CURSOR_RIGHT_ARROW 0
#define GLUT_CURSOR_LEFT_ARROW 1
/* Symbolic cursor shapes. */
#define GLUT_CURSOR_INFO 2
#define GLUT_CURSOR_DESTROY 3
#define GLUT_CURSOR_HELP 4
#define GLUT_CURSOR_CYCLE 5
#define GLUT_CURSOR_SPRAY 6
#define GLUT_CURSOR_WAIT 7
#define GLUT_CURSOR_TEXT 8
#define GLUT_CURSOR_CROSSHAIR 9
/* Directional cursors. */
#define GLUT_CURSOR_UP_DOWN 10
#define GLUT_CURSOR_LEFT_RIGHT 11
/* Sizing cursors. */
#define GLUT_CURSOR_TOP_SIDE 12
#define GLUT_CURSOR_BOTTOM_SIDE 13
#define GLUT_CURSOR_LEFT_SIDE 14
#define GLUT_CURSOR_RIGHT_SIDE 15
#define GLUT_CURSOR_TOP_LEFT_CORNER 16
#define GLUT_CURSOR_TOP_RIGHT_CORNER 17
#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18
#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19
/* Inherit from parent window. */
#define GLUT_CURSOR_INHERIT 100
/* Blank cursor. */
#define GLUT_CURSOR_NONE 101
/* Fullscreen crosshair (if available). */
#define GLUT_CURSOR_FULL_CROSSHAIR 102
#endif
/* GLUT initialization sub-API. */
GLUTAPI void GLUTAPIENTRY glutInit(int *argcp, char **argv);
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI void GLUTAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static void GLUTAPIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
#define glutInit glutInit_ATEXIT_HACK
#endif
#endif
GLUTAPI void GLUTAPIENTRY glutInitDisplayMode(unsigned int mode);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutInitDisplayString(const char *string);
#endif
GLUTAPI void GLUTAPIENTRY glutInitWindowPosition(int x, int y);
GLUTAPI void GLUTAPIENTRY glutInitWindowSize(int width, int height);
GLUTAPI void GLUTAPIENTRY glutMainLoop(void);
/* GLUT window sub-API. */
GLUTAPI int GLUTAPIENTRY glutCreateWindow(const char *title);
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI int GLUTAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static int GLUTAPIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
#endif
#endif
GLUTAPI int GLUTAPIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height);
GLUTAPI void GLUTAPIENTRY glutDestroyWindow(int win);
GLUTAPI void GLUTAPIENTRY glutPostRedisplay(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
GLUTAPI void GLUTAPIENTRY glutPostWindowRedisplay(int win);
#endif
GLUTAPI void GLUTAPIENTRY glutSwapBuffers(void);
GLUTAPI int GLUTAPIENTRY glutGetWindow(void);
GLUTAPI void GLUTAPIENTRY glutSetWindow(int win);
GLUTAPI void GLUTAPIENTRY glutSetWindowTitle(const char *title);
GLUTAPI void GLUTAPIENTRY glutSetIconTitle(const char *title);
GLUTAPI void GLUTAPIENTRY glutPositionWindow(int x, int y);
GLUTAPI void GLUTAPIENTRY glutReshapeWindow(int width, int height);
GLUTAPI void GLUTAPIENTRY glutPopWindow(void);
GLUTAPI void GLUTAPIENTRY glutPushWindow(void);
GLUTAPI void GLUTAPIENTRY glutIconifyWindow(void);
GLUTAPI void GLUTAPIENTRY glutShowWindow(void);
GLUTAPI void GLUTAPIENTRY glutHideWindow(void);
#if (GLUT_API_VERSION >= 3)
GLUTAPI void GLUTAPIENTRY glutFullScreen(void);
GLUTAPI void GLUTAPIENTRY glutSetCursor(int cursor);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutWarpPointer(int x, int y);
#endif
/* GLUT overlay sub-API. */
GLUTAPI void GLUTAPIENTRY glutEstablishOverlay(void);
GLUTAPI void GLUTAPIENTRY glutRemoveOverlay(void);
GLUTAPI void GLUTAPIENTRY glutUseLayer(GLenum layer);
GLUTAPI void GLUTAPIENTRY glutPostOverlayRedisplay(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
GLUTAPI void GLUTAPIENTRY glutPostWindowOverlayRedisplay(int win);
#endif
GLUTAPI void GLUTAPIENTRY glutShowOverlay(void);
GLUTAPI void GLUTAPIENTRY glutHideOverlay(void);
#endif
/* GLUT menu sub-API. */
GLUTAPI int GLUTAPIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int));
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI int GLUTAPIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static int GLUTAPIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); }
#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
#endif
#endif
GLUTAPI void GLUTAPIENTRY glutDestroyMenu(int menu);
GLUTAPI int GLUTAPIENTRY glutGetMenu(void);
GLUTAPI void GLUTAPIENTRY glutSetMenu(int menu);
GLUTAPI void GLUTAPIENTRY glutAddMenuEntry(const char *label, int value);
GLUTAPI void GLUTAPIENTRY glutAddSubMenu(const char *label, int submenu);
GLUTAPI void GLUTAPIENTRY glutChangeToMenuEntry(int item, const char *label, int value);
GLUTAPI void GLUTAPIENTRY glutChangeToSubMenu(int item, const char *label, int submenu);
GLUTAPI void GLUTAPIENTRY glutRemoveMenuItem(int item);
GLUTAPI void GLUTAPIENTRY glutAttachMenu(int button);
GLUTAPI void GLUTAPIENTRY glutDetachMenu(int button);
/* GLUT window callback sub-API. */
GLUTAPI void GLUTAPIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void));
GLUTAPI void GLUTAPIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height));
GLUTAPI void GLUTAPIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
GLUTAPI void GLUTAPIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state));
GLUTAPI void GLUTAPIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state));
GLUTAPI void GLUTAPIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void));
GLUTAPI void GLUTAPIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value);
GLUTAPI void GLUTAPIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state));
#if (GLUT_API_VERSION >= 2)
GLUTAPI void GLUTAPIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
GLUTAPI void GLUTAPIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
GLUTAPI void GLUTAPIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state));
GLUTAPI void GLUTAPIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state));
GLUTAPI void GLUTAPIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value));
GLUTAPI void GLUTAPIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
#if (GLUT_API_VERSION >= 3)
GLUTAPI void GLUTAPIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y));
GLUTAPI void GLUTAPIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void));
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state));
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
GLUTAPI void GLUTAPIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval);
#endif
#endif
#endif
/* GLUT color index sub-API. */
GLUTAPI void GLUTAPIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue);
GLUTAPI GLfloat GLUTAPIENTRY glutGetColor(int ndx, int component);
GLUTAPI void GLUTAPIENTRY glutCopyColormap(int win);
/* GLUT state retrieval sub-API. */
GLUTAPI int GLUTAPIENTRY glutGet(GLenum type);
GLUTAPI int GLUTAPIENTRY glutDeviceGet(GLenum type);
#if (GLUT_API_VERSION >= 2)
/* GLUT extension support sub-API */
GLUTAPI int GLUTAPIENTRY glutExtensionSupported(const char *name);
#endif
#if (GLUT_API_VERSION >= 3)
GLUTAPI int GLUTAPIENTRY glutGetModifiers(void);
GLUTAPI int GLUTAPIENTRY glutLayerGet(GLenum type);
#endif
/* GLUT font sub-API */
GLUTAPI void GLUTAPIENTRY glutBitmapCharacter(void *font, int character);
GLUTAPI int GLUTAPIENTRY glutBitmapWidth(void *font, int character);
GLUTAPI void GLUTAPIENTRY glutStrokeCharacter(void *font, int character);
GLUTAPI int GLUTAPIENTRY glutStrokeWidth(void *font, int character);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI int GLUTAPIENTRY glutBitmapLength(void *font, const unsigned char *string);
GLUTAPI int GLUTAPIENTRY glutStrokeLength(void *font, const unsigned char *string);
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 17)
GLUTAPI float GLUTAPIENTRY glutStrokeWidthf(void *font, int character);
GLUTAPI float GLUTAPIENTRY glutStrokeLengthf(void *font, const unsigned char *string);
#endif
/* GLUT pre-built models sub-API */
GLUTAPI void GLUTAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutWireCube(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutSolidCube(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
GLUTAPI void GLUTAPIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
GLUTAPI void GLUTAPIENTRY glutWireDodecahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidDodecahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireTeapot(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutSolidTeapot(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutWireOctahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidOctahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireTetrahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidTetrahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireIcosahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidIcosahedron(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
/* GLUT video resize sub-API. */
GLUTAPI int GLUTAPIENTRY glutVideoResizeGet(GLenum param);
GLUTAPI void GLUTAPIENTRY glutSetupVideoResizing(void);
GLUTAPI void GLUTAPIENTRY glutStopVideoResizing(void);
GLUTAPI void GLUTAPIENTRY glutVideoResize(int x, int y, int width, int height);
GLUTAPI void GLUTAPIENTRY glutVideoPan(int x, int y, int width, int height);
/* GLUT debugging sub-API. */
GLUTAPI void GLUTAPIENTRY glutReportErrors(void);
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
/* GLUT device control sub-API. */
/* glutSetKeyRepeat modes. */
#define GLUT_KEY_REPEAT_OFF 0
#define GLUT_KEY_REPEAT_ON 1
#define GLUT_KEY_REPEAT_DEFAULT 2
/* Joystick button masks. */
#define GLUT_JOYSTICK_BUTTON_A 1
#define GLUT_JOYSTICK_BUTTON_B 2
#define GLUT_JOYSTICK_BUTTON_C 4
#define GLUT_JOYSTICK_BUTTON_D 8
GLUTAPI void GLUTAPIENTRY glutIgnoreKeyRepeat(int ignore);
GLUTAPI void GLUTAPIENTRY glutSetKeyRepeat(int repeatMode);
GLUTAPI void GLUTAPIENTRY glutForceJoystickFunc(void);
/* GLUT game mode sub-API. */
/* glutGameModeGet. */
#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0)
#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1)
#define GLUT_GAME_MODE_WIDTH ((GLenum) 2)
#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3)
#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4)
#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5)
#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6)
GLUTAPI void GLUTAPIENTRY glutGameModeString(const char *string);
GLUTAPI int GLUTAPIENTRY glutEnterGameMode(void);
GLUTAPI void GLUTAPIENTRY glutLeaveGameMode(void);
GLUTAPI int GLUTAPIENTRY glutGameModeGet(GLenum mode);
#endif
#ifdef __cplusplus
}
#endif
#ifdef GLUT_APIENTRY_DEFINED
# undef GLUT_APIENTRY_DEFINED
# undef APIENTRY
#endif
#ifdef GLUT_WINGDIAPI_DEFINED
# undef GLUT_WINGDIAPI_DEFINED
# undef WINGDIAPI
#endif
#ifdef GLUT_DEFINED___CDECL
# undef GLUT_DEFINED___CDECL
# undef __cdecl
#endif
#ifdef GLUT_DEFINED__CRTIMP
# undef GLUT_DEFINED__CRTIMP
# undef _CRTIMP
#endif
#endif /* __glut_h__ */

1948
Extras/sph/common/image.cpp Normal file

File diff suppressed because it is too large Load Diff

188
Extras/sph/common/image.h Normal file
View File

@@ -0,0 +1,188 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
class Image;
#ifndef IMAGE_H
#define IMAGE_H
#include "common_defs.h"
#include <stdio.h>
#ifdef _MSC_VER
#include <windows.h>
#endif
// Image class code below...
#define IRED 0
#define IGREEN 1
#define IBLUE 2
#define IALPHA 3
class Pixel {
public:
Pixel () { r=0;g=0;b=0;a=1;}
Pixel ( double r_, double g_, double b_ ) {r = r_; g = g_; b = b_; a = 1.0; }
Pixel ( double r_, double g_, double b_, double a_ ) {r = r_; g = g_; b = b_; a = a_; }
double r;
double g;
double b;
double a;
};
#if defined(_MSC_VER) && defined(USE_JPEG)
#pragma comment(lib, "jpegd.lib" )
#endif
/*
* generic multi channel 8-bit max image class. can read and write
* BMP, ascii PNM, and JPG file formats, and supports some useful OpenGL
* calls.
*
* get and set pixel methods use doubles from 0.0 to 1.0. these
* values are mapped to integer values from 0 to the maximum value
* allowed by the number of bits per channel in the image.
*/
class Image {
public:
Image ();
~Image ();
// create empty image with specified characteristics
Image (int width_, int height_);
Image (int width_, int height_, int channels_);
Image (int width_, int height_, int channels_,
int bits_);
// create image and read data from filename
// use good() or bad() to check success
Image (const char* filename);
// copy constructor and assignment operator
// _deep_ copy!
Image (const Image& image);
Image& operator= (const Image& image);
// accessors
int getWidth () { return width; }
int getHeight () { return height; }
int getChannels () { return channels; }
int getBits () { return bits; }
unsigned char* getPixels () { return pixels; }
void create ( int width_, int height_, int channels_ );
void refresh ();
void draw ();
void draw ( float x, float y );
// unsafe! use at your own risk!
void setPixels ( unsigned char *newPixels );
// check if the image is valid
bool good ();
bool bad ();
// set all the pixel data
void clear ();
void clear ( Pixel pixel );
// retrieve pixel data. methods with _ at the
// end of their name return 0.0 if the x and y
// are out of range. otherwise, an assertion
// failure occurs
double getPixel (int x, int y, int channel);
double getPixel_ (int x, int y, int channel);
Pixel getPixel (int x, int y);
Pixel getPixel_ (int x, int y);
Pixel& getPixel (int x, int y, Pixel& pixel);
Pixel& getPixel_ (int x, int y, Pixel& pixel);
// set pixel data. if x and y are out of range,
// an assertion failure occurs
void setPixel (int x, int y, int channel, double value);
void setPixel_ (int x, int y, int channel, double value);
void setPixel (int x, int y, Pixel pixel);
void setPixel_ (int x, int y, Pixel pixel);
void setPixel4 ( int x, int y, Pixel pixel );
void setAlpha (int x, int y, double value);
#ifndef DISABLE_OPENGL
// OpenGL call wrappers
void glReadPixelsWrapper ();
void glDrawPixelsWrapper ();
void glTexImage2DWrapper ();
void glTexImageCubeWrapper ( int i );
void glTexSubImage2DWrapper ( int x, int y);
#endif
// top-level file read and write calls,
// determines file type
int read (const char* filename);
int read (const char* filename, const char* alphaname );
int write (const char* filename);
int readPaletteBMP ( FILE* fp, RGBQUAD*& palette, int bit_count );
// BMP specific read and write calls
int readBMP (const char* filename);
int readBMP (FILE* file, FILE* file_a, bool bBaseImg );
int writeBMP (const char* filename);
int writeBMP (FILE* file);
// PNM specific read and write calls
int readPNM (const char* filename);
int readPNM (FILE* file);
int writePNM (const char* filename);
int writePNM (FILE* file);
#ifdef USE_JPEG
// JPG specific read and write calls
int readJPG (const char* filename);
int readJPG (FILE* file);
int writeJPG (const char* filename);
int writeJPG (FILE* file);
#endif
private:
int index(int x, int y, int c);
int width;
int height;
int channels; // number of channels per pixel
int bits; // number of bits per channel
int maxValue; // max that can be stored in bits
unsigned char* pixels; // image data
bool owns; // if image owns pixels
unsigned int imgID;
};
#endif // IMAGE_H

File diff suppressed because it is too large Load Diff

2046
Extras/sph/common/matrix.cci Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "matrix.h"

429
Extras/sph/common/matrix.h Normal file
View File

@@ -0,0 +1,429 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory.h>
#include <math.h>
//*********** NOTE
//
// LOOK AT MovieTrackPoint. IN ORDER FOR VECTORS AND MATRICIES TO BE USED IN OBJECTS
// THAT WILL BE USED IN stl::vectors, THEIR CONSTRUCTORS AND OPERATORS MUST TAKE ONLY
// const PARAMETERS. LOOK AT MatrixF and Vector2DF.. THIS WAS NOT YET DONE WITH
// THE OTHER MATRIX AND VECTOR CLASSES (Vector2DC, Vector2DI, MatrixC, MatrixI, ...)
//
#ifndef MATRIX_DEF
#define MATRIX_DEF
#include "vector.h"
#include "mdebug.h"
//#define MATRIX_INITIALIZE // Initializes vectors
class MatrixC; // Forward Referencing
class MatrixI;
class MatrixF;
class Matrix {
public:
// Member Virtual Functions
virtual Matrix &operator= (unsigned char c)=0;
virtual Matrix &operator= (int c)=0;
virtual Matrix &operator= (double c)=0;
virtual Matrix &operator= (MatrixC &op)=0;
virtual Matrix &operator= (MatrixI &op)=0;
virtual Matrix &operator= (MatrixF &op)=0;
virtual Matrix &operator+= (unsigned char c)=0;
virtual Matrix &operator+= (int c)=0;
virtual Matrix &operator+= (double c)=0;
virtual Matrix &operator+= (MatrixC &op)=0;
virtual Matrix &operator+= (MatrixI &op)=0;
virtual Matrix &operator+= (MatrixF &op)=0;
virtual Matrix &operator-= (unsigned char c)=0;
virtual Matrix &operator-= (int c)=0;
virtual Matrix &operator-= (double c)=0;
virtual Matrix &operator-= (MatrixC &op)=0;
virtual Matrix &operator-= (MatrixI &op)=0;
virtual Matrix &operator-= (MatrixF &op)=0;
virtual Matrix &operator*= (unsigned char c)=0;
virtual Matrix &operator*= (int c)=0;
virtual Matrix &operator*= (double c)=0;
virtual Matrix &operator*= (MatrixC &op)=0;
virtual Matrix &operator*= (MatrixI &op)=0;
virtual Matrix &operator*= (MatrixF &op)=0;
virtual Matrix &operator/= (unsigned char c)=0;
virtual Matrix &operator/= (int c)=0;
virtual Matrix &operator/= (double c)=0;
virtual Matrix &operator/= (MatrixC &op)=0;
virtual Matrix &operator/= (MatrixI &op)=0;
virtual Matrix &operator/= (MatrixF &op)=0;
virtual Matrix &Multiply (MatrixF &op)=0;
virtual Matrix &Resize (int x, int y)=0;
virtual Matrix &ResizeSafe (int x, int y)=0;
virtual Matrix &InsertRow (int r)=0;
virtual Matrix &InsertCol (int c)=0;
virtual Matrix &Transpose (void)=0;
virtual Matrix &Identity (int order)=0;
/*inline Matrix &RotateX (double ang);
inline Matrix &RotateY (double ang);
inline Matrix &RotateZ (double ang); */
virtual Matrix &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3)=0;
virtual Matrix &GaussJordan (MatrixF &b) { return *this; }
virtual Matrix &ConjugateGradient (MatrixF &b) { return *this; }
virtual int GetRows(void)=0;
virtual int GetCols(void)=0;
virtual int GetLength(void)=0;
virtual unsigned char *GetDataC (void)=0;
virtual int *GetDataI (void)=0;
virtual double *GetDataF (void)=0;
virtual double GetF (int r, int c);
};
// MatrixC Declaration
#define VNAME C
#define VTYPE unsigned char
class MatrixC {
public:
VTYPE *data;
int rows, cols, len;
// Constructors/Destructors
inline MatrixC ();
inline ~MatrixC ();
inline MatrixC (int r, int c);
// Member Functions
inline VTYPE &operator () (int c, int r);
inline MatrixC &operator= (unsigned char c);
inline MatrixC &operator= (int c);
inline MatrixC &operator= (double c);
inline MatrixC &operator= (MatrixC &op);
inline MatrixC &operator= (MatrixI &op);
inline MatrixC &operator= (MatrixF &op);
inline MatrixC &operator+= (unsigned char c);
inline MatrixC &operator+= (int c);
inline MatrixC &operator+= (double c);
inline MatrixC &operator+= (MatrixC &op);
inline MatrixC &operator+= (MatrixI &op);
inline MatrixC &operator+= (MatrixF &op);
inline MatrixC &operator-= (unsigned char c);
inline MatrixC &operator-= (int c);
inline MatrixC &operator-= (double c);
inline MatrixC &operator-= (MatrixC &op);
inline MatrixC &operator-= (MatrixI &op);
inline MatrixC &operator-= (MatrixF &op);
inline MatrixC &operator*= (unsigned char c);
inline MatrixC &operator*= (int c);
inline MatrixC &operator*= (double c);
inline MatrixC &operator*= (MatrixC &op);
inline MatrixC &operator*= (MatrixI &op);
inline MatrixC &operator*= (MatrixF &op);
inline MatrixC &operator/= (unsigned char c);
inline MatrixC &operator/= (int c);
inline MatrixC &operator/= (double c);
inline MatrixC &operator/= (MatrixC &op);
inline MatrixC &operator/= (MatrixI &op);
inline MatrixC &operator/= (MatrixF &op);
inline MatrixC &Multiply (MatrixF &op);
inline MatrixC &Resize (int x, int y);
inline MatrixC &ResizeSafe (int x, int y);
inline MatrixC &InsertRow (int r);
inline MatrixC &InsertCol (int c);
inline MatrixC &Transpose (void);
inline MatrixC &Identity (int order);
inline MatrixC &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3);
inline MatrixC &GaussJordan (MatrixF &b);
inline int GetX();
inline int GetY();
inline int GetRows(void);
inline int GetCols(void);
inline int GetLength(void);
inline VTYPE *GetData(void);
inline unsigned char *GetDataC (void) {return data;}
inline int *GetDataI (void) {return NULL;}
inline double *GetDataF (void) {return NULL;}
inline double GetF (int r, int c);
};
#undef VNAME
#undef VTYPE
// MatrixI Declaration
#define VNAME I
#define VTYPE int
class MatrixI {
public:
VTYPE *data;
int rows, cols, len;
// Constructors/Destructors
inline MatrixI ();
inline ~MatrixI ();
inline MatrixI (int r, int c);
// Member Functions
inline VTYPE &operator () (int c, int r);
inline MatrixI &operator= (unsigned char c);
inline MatrixI &operator= (int c);
inline MatrixI &operator= (double c);
inline MatrixI &operator= (MatrixC &op);
inline MatrixI &operator= (MatrixI &op);
inline MatrixI &operator= (MatrixF &op);
inline MatrixI &operator+= (unsigned char c);
inline MatrixI &operator+= (int c);
inline MatrixI &operator+= (double c);
inline MatrixI &operator+= (MatrixC &op);
inline MatrixI &operator+= (MatrixI &op);
inline MatrixI &operator+= (MatrixF &op);
inline MatrixI &operator-= (unsigned char c);
inline MatrixI &operator-= (int c);
inline MatrixI &operator-= (double c);
inline MatrixI &operator-= (MatrixC &op);
inline MatrixI &operator-= (MatrixI &op);
inline MatrixI &operator-= (MatrixF &op);
inline MatrixI &operator*= (unsigned char c);
inline MatrixI &operator*= (int c);
inline MatrixI &operator*= (double c);
inline MatrixI &operator*= (MatrixC &op);
inline MatrixI &operator*= (MatrixI &op);
inline MatrixI &operator*= (MatrixF &op);
inline MatrixI &operator/= (unsigned char c);
inline MatrixI &operator/= (int c);
inline MatrixI &operator/= (double c);
inline MatrixI &operator/= (MatrixC &op);
inline MatrixI &operator/= (MatrixI &op);
inline MatrixI &operator/= (MatrixF &op);
inline MatrixI &Multiply (MatrixF &op);
inline MatrixI &Resize (int x, int y);
inline MatrixI &ResizeSafe (int x, int y);
inline MatrixI &InsertRow (int r);
inline MatrixI &InsertCol (int c);
inline MatrixI &Transpose (void);
inline MatrixI &Identity (int order);
inline MatrixI &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3);
inline MatrixI &GaussJordan (MatrixF &b);
inline int GetX();
inline int GetY();
inline int GetRows(void);
inline int GetCols(void);
inline int GetLength(void);
inline VTYPE *GetData(void);
inline unsigned char *GetDataC (void) {return NULL;}
inline int *GetDataI (void) {return data;}
inline double *GetDataF (void) {return NULL;}
inline double GetF (int r, int c);
};
#undef VNAME
#undef VTYPE
// MatrixF Declaration
#define VNAME F
#define VTYPE double
class MatrixF {
public:
VTYPE *data;
int rows, cols, len;
// Constructors/Destructors
inline MatrixF ();
inline ~MatrixF ();
inline MatrixF (const int r, const int c);
// Member Functions
inline VTYPE GetVal ( int c, int r );
inline VTYPE &operator () (const int c, const int r);
inline MatrixF &operator= (const unsigned char c);
inline MatrixF &operator= (const int c);
inline MatrixF &operator= (const double c);
inline MatrixF &operator= (const MatrixC &op);
inline MatrixF &operator= (const MatrixI &op);
inline MatrixF &operator= (const MatrixF &op);
inline MatrixF &operator+= (const unsigned char c);
inline MatrixF &operator+= (const int c);
inline MatrixF &operator+= (const double c);
inline MatrixF &operator+= (const MatrixC &op);
inline MatrixF &operator+= (const MatrixI &op);
inline MatrixF &operator+= (const MatrixF &op);
inline MatrixF &operator-= (const unsigned char c);
inline MatrixF &operator-= (const int c);
inline MatrixF &operator-= (const double c);
inline MatrixF &operator-= (const MatrixC &op);
inline MatrixF &operator-= (const MatrixI &op);
inline MatrixF &operator-= (const MatrixF &op);
inline MatrixF &operator*= (const unsigned char c);
inline MatrixF &operator*= (const int c);
inline MatrixF &operator*= (const double c);
inline MatrixF &operator*= (const MatrixC &op);
inline MatrixF &operator*= (const MatrixI &op);
inline MatrixF &operator*= (const MatrixF &op);
inline MatrixF &operator/= (const unsigned char c);
inline MatrixF &operator/= (const int c);
inline MatrixF &operator/= (const double c);
inline MatrixF &operator/= (const MatrixC &op);
inline MatrixF &operator/= (const MatrixI &op);
inline MatrixF &operator/= (const MatrixF &op);
inline MatrixF &Multiply4x4 (const MatrixF &op);
inline MatrixF &Multiply (const MatrixF &op);
inline MatrixF &Resize (const int x, const int y);
inline MatrixF &ResizeSafe (const int x, const int y);
inline MatrixF &InsertRow (const int r);
inline MatrixF &InsertCol (const int c);
inline MatrixF &Transpose (void);
inline MatrixF &Identity (const int order);
inline MatrixF &RotateX (const double ang);
inline MatrixF &RotateY (const double ang);
inline MatrixF &RotateZ (const double ang);
inline MatrixF &Ortho (double sx, double sy, double n, double f);
inline MatrixF &Translate (double tx, double ty, double tz);
inline MatrixF &Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3);
inline MatrixF &GaussJordan (MatrixF &b);
inline MatrixF &ConjugateGradient (MatrixF &b);
inline MatrixF &Submatrix ( MatrixF& b, int mx, int my);
inline MatrixF &MatrixVector5 (MatrixF& x, int mrows, MatrixF& b );
inline MatrixF &ConjugateGradient5 (MatrixF &b, int mrows );
inline double Dot ( MatrixF& b );
inline void Print ( char* fname );
inline int GetX();
inline int GetY();
inline int GetRows(void);
inline int GetCols(void);
inline int GetLength(void);
inline VTYPE *GetData(void);
inline void GetRowVec (int r, Vector3DF &v);
inline unsigned char *GetDataC (void) const {return NULL;}
inline int *GetDataI (void) const {return NULL;}
inline double *GetDataF (void) const {return data;}
inline double GetF (const int r, const int c);
};
#undef VNAME
#undef VTYPE
// MatrixF Declaration
#define VNAME F
#define VTYPE float
class Matrix4F {
public:
VTYPE data[16];
// Constructors/Destructors
inline Matrix4F ();
// Member Functions
inline VTYPE &operator () (const int n) { return data[n]; }
inline VTYPE &operator () (const int c, const int r) { return data[ (r<<2)+c ]; }
inline Matrix4F &operator= (const unsigned char c);
inline Matrix4F &operator= (const int c);
inline Matrix4F &operator= (const double c);
inline Matrix4F &operator+= (const unsigned char c);
inline Matrix4F &operator+= (const int c);
inline Matrix4F &operator+= (const double c);
inline Matrix4F &operator-= (const unsigned char c);
inline Matrix4F &operator-= (const int c);
inline Matrix4F &operator-= (const double c);
inline Matrix4F &operator*= (const unsigned char c);
inline Matrix4F &operator*= (const int c);
inline Matrix4F &operator*= (const double c);
inline Matrix4F &operator/= (const unsigned char c);
inline Matrix4F &operator/= (const int c);
inline Matrix4F &operator/= (const double c);
inline Matrix4F &Multiply (const Matrix4F &op);
inline Matrix4F &Transpose (void);
inline Matrix4F &Identity (const int order);
inline Matrix4F &RotateX (const double ang);
inline Matrix4F &RotateY (const double ang);
inline Matrix4F &RotateZ (const double ang);
inline Matrix4F &Ortho (double sx, double sy, double n, double f);
inline Matrix4F &Translate (double tx, double ty, double tz);
inline Matrix4F &Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3);
// Scale-Rotate-Translate (compound matrix)
inline Matrix4F &SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s);
inline Matrix4F &SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s);
// invTranslate-invRotate-invScale (compound matrix)
inline Matrix4F &InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s);
inline Matrix4F &InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s);
inline int GetX() { return 4; }
inline int GetY() { return 4; }
inline int GetRows(void) { return 4; }
inline int GetCols(void) { return 4; }
inline int GetLength(void) { return 16; }
inline VTYPE *GetData(void) { return data; }
inline void GetRowVec (int r, Vector3DF &v);
inline unsigned char *GetDataC (void) const {return NULL;}
inline int *GetDataI (void) const {return NULL;}
inline float *GetDataF (void) const {return (float*) data;}
inline float GetF (const int r, const int c);
};
#undef VNAME
#undef VTYPE
// Matrix Code Definitions (Inlined)
#include "matrix.cci"
#endif

View File

@@ -0,0 +1,583 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
//#define MEMORY_DEBUG // Overloads the new and delete operators
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "mdebug.h"
#ifdef _MSC_VER
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <conio.h>
#endif
CDebug debug;
CError error;
//------------------------------------------------- DEBUG CLASS
CDebug::CDebug ()
{
m_OutName = "debug.txt";
m_bStarted = false;
m_bToFile = true;
m_bToSysbox = true;
m_bToCons = false;
m_OutFile = NULL;
m_OutCons = NULL;
Start ();
}
CDebug::~CDebug (void)
{
Stop ();
}
void CDebug::Start ()
{
if ( m_bStarted ) Stop ();
if ( m_bToFile ) {
char fn[200];
#ifdef _MSC_VER
strcpy_s ( fn, 200, m_OutName.c_str () );
fopen_s ( &m_OutFile, fn, "w+t" );
#else
strncpy ( fn, m_OutName.c_str(), 200 );
m_OutFile = fopen( fn, "w+" );
#endif
if ( m_OutFile == 0x0 ) {
exit ( EXIT_FAILURE ); // error: Cannot create debug file
}
m_bStarted = true;
Print ( "debug", "CDebug started to file.\n");
}
m_bStarted = true;
}
void CDebug::Exit ( int code )
{
if ( !m_bToSysbox ) {
#ifdef _MSC_VER
_getch();
#endif
}
exit ( code );
}
void CDebug::Stop ()
{
if ( m_bStarted ) {
if ( m_bToFile ) {
Print ( "debug", "CDebug stopped.");
fclose ( m_OutFile );
}
}
m_bStarted = false;
}
void CDebug::SendToFile ( char* fname )
{
if (m_bStarted) Stop ();
m_bToFile = true;
m_OutName = fname;
}
void CDebug::SendToConsole ( bool tf )
{
m_bToCons = tf;
if ( tf ) {
#ifdef _MSC_VER
AllocConsole ();
long lStdHandle = (long) GetStdHandle( STD_OUTPUT_HANDLE );
int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
m_OutCons = _fdopen( hConHandle, "w" );
#endif
}
}
void CDebug::SendToSysbox ( bool tf )
{
m_bToSysbox = tf;
}
void CDebug::Print ( std::string subsys, std::string msg )
{
if ( m_bStarted ) {
if ( m_bToFile ) {
fprintf ( m_OutFile, "%s: %s\n", subsys.c_str(), msg.c_str() );
fflush ( m_OutFile);
}
if ( m_bToCons ) {
#ifdef _MSC_VER
fprintf ( m_OutCons, "%s: %s\n", subsys.c_str(), msg.c_str() );
fflush ( m_OutCons );
#else
printf ( "%s: %s\n", subsys.c_str(), msg.c_str() );
#endif
}
}
}
void CDebug::Print (char* msg)
{
if ( m_bStarted ) {
if ( m_bToFile ) {
fprintf ( m_OutFile, "%s", msg );
fflush ( m_OutFile );
}
if ( m_bToCons ) {
#ifdef _MSC_VER
fprintf ( m_OutCons, "%s", msg );
fflush ( m_OutCons );
#else
printf ( "%s", msg );
#endif
}
}
}
void CDebug::Print ( std::string msg )
{
if ( m_bStarted ) {
if ( m_bToFile ) {
fprintf ( m_OutFile, "%s", msg.c_str() );
fflush ( m_OutFile );
}
if ( m_bToCons ) {
#ifdef _MSC_VER
fprintf ( m_OutCons, "%s", msg.c_str() );
fflush ( m_OutCons );
#else
printf ( "%s", msg.c_str() );
#endif
}
}
}
void CDebug::PrintF ( std::string substr, char* format, ... )
{
// Note: This is the >only< way to do this. There is no general way to
// pass on all the arguments from one ellipsis function to another.
// The function vfprintf was specially designed to allow this.
if ( m_bStarted ) {
if ( m_bToFile ) {
va_list argptr;
va_start (argptr, format);
fprintf ( m_OutFile, "%s: ", substr.c_str() );
vfprintf ( m_OutFile, format, argptr);
va_end (argptr);
fflush ( m_OutFile );
}
if ( m_bToCons ) {
#ifdef _MSC_VER
va_list argptr;
va_start (argptr, format);
fprintf ( m_OutCons, "%s: ", substr.c_str() );
vfprintf ( m_OutCons, format, argptr);
va_end (argptr);
fflush ( m_OutCons );
#else
va_list argptr;
va_start (argptr, format);
printf ( "%s: ", substr.c_str() );
vprintf ( format, argptr);
va_end (argptr);
#endif
}
}
}
void CDebug::Printf ( char* format, ... )
{
// Note: This is the >only< way to do this. There is no general way to
// pass on all the arguments from one ellipsis function to another.
// The function vfprintf was specially designed to allow this.
if ( m_bStarted ) {
if ( m_bToFile ) {
va_list argptr;
va_start (argptr, format);
vfprintf ( m_OutFile, format, argptr);
va_end (argptr);
fflush ( m_OutFile );
}
if ( m_bToCons ) {
#ifdef _MSC_VER
va_list argptr;
va_start (argptr, format);
vfprintf ( m_OutCons, format, argptr);
va_end (argptr);
fflush ( m_OutCons );
#else
va_list argptr;
va_start (argptr, format);
vprintf ( format, argptr);
va_end (argptr);
#endif
}
}
}
void CDebug::PrintErr ( std::string errid, std::string subsys, std::string msg, std::string sysbox )
{
if ( m_bStarted ) {
if ( m_bToFile ) {
fprintf ( m_OutFile, "%s: ERROR: %s\n", subsys.c_str(), msg.c_str() );
fflush ( m_OutFile );
}
if ( m_bToCons ) {
#ifdef _MSC_VER
fprintf ( m_OutCons, "%s: ERROR: %s\n", subsys.c_str(), msg.c_str() );
fflush ( m_OutCons );
#else
printf ( "%s: ERROR[%s] %s\n", subsys.c_str(), errid.c_str(), msg.c_str() );
#endif
}
if ( m_bToSysbox ) {
char disp[4000];
char caption[200];
#ifdef _MSC_VER
// Message boxes for Windows
strcpy_s ( caption, 200, "Mint - Error" );
strcpy_s ( disp, 4000, sysbox.c_str());
#include <windows.h>
int hr = MessageBoxA ( 0x0, disp, caption, MB_OK);
#else
strncpy ( caption, m_ErrorSubsys.c_str(), 200 );
strncpy ( disp, msg.c_str(), 4000 );
#endif
}
}
}
//-------------------------------------------------------------------- Error Class Code
//
// This software is released under the LGPL Open Source Liscense.
// See the documentation included with this source code for terms of modification,
// distribution and re-release.
//
// Original Copyright (C) 2002 Rama C. Hoetzlein, GameX R4
//
CError::CError ()
{
m_Errors.clear ();
m_ErrorID = "";
m_ErrorSubsys = "";
m_ErrorMsg = "";
m_ErrorFunc = "";
m_ErrorFix = "";
m_ErrorExtra = "";
}
void CError::Start ()
{
Start ( "" );
}
void CError::Start ( char* fname )
{
if ( fname != 0x0 && strlen(fname) > 0 ) {
// Read error message file. NOT YET IMPLEMENTED
} else {
debug.Print ( "error", "No error file loaded." );
}
debug.Print ( "error", "Error handler started." );
m_bStarted = true;
}
void CError::OutputMessage ()
{
// Create sysbox message
std::string box_msg;
box_msg = "Subsystem: " + m_ErrorSubsys + "\n\n";
box_msg += "Error: " + m_ErrorMsg + "\n";
if ( m_ErrorExtra.length() > 0) box_msg += "Info: " + m_ErrorExtra + "\n";
if ( m_ErrorFix.length() > 0) box_msg += "\nFix: " + m_ErrorFix + "\n";
if ( m_ErrorID.length() > 0 ) box_msg += "Error ID: " + m_ErrorID + "\n";
if ( m_ErrorFunc.length() > 0 ) box_msg += "Function: " + m_ErrorFunc + "\n";
// Error output to debug file
debug.PrintErr ( m_ErrorID, m_ErrorSubsys, m_ErrorMsg, box_msg );
}
void CError::Exit ( int code )
{
debug.Exit ( code );
}
void CError::Print ( char* msg)
{
// User-level error (no additional info)
m_ErrorID = "";
m_ErrorSubsys = "undef";
m_ErrorMsg = msg;
m_ErrorFunc = "";
m_ErrorFix = "";
m_ErrorExtra = "";
OutputMessage ();
}
void CError::Print ( std::string msg )
{
// User-level error (no additional info)
m_ErrorID = "";
m_ErrorSubsys = "undef";
m_ErrorMsg = msg;
m_ErrorFunc = "";
m_ErrorFix = "";
m_ErrorExtra = "";
OutputMessage ();
}
void CError::Print ( std::string subsys, std::string msg ){
// Unregistered error
m_ErrorID = "";
m_ErrorSubsys = subsys;
m_ErrorMsg = msg;
m_ErrorFunc = "";
m_ErrorFix = "";
m_ErrorExtra = "";
OutputMessage ();
}
void CError::PrintF ( std::string subsys, char* msg, ... )
{
char buf[2000];
va_list argptr;
m_ErrorID = "";
m_ErrorSubsys = subsys;
va_start(argptr, msg);
#ifdef _MSC_VER
vsprintf_s (buf, 2000, msg, argptr);
#else
vsnprintf(buf, 2000, msg, argptr);
#endif
va_end (argptr);
m_ErrorMsg = buf;
m_ErrorFunc = "";
m_ErrorFix = "";
m_ErrorExtra = "";
OutputMessage ();
}
void CError::PrintErr ( std::string err )
{
// Registered error - NOT YET IMPLEMENTED
// CErrorMsg* msg = m_
}
void CError::PrintErrDX ( std::string err, int result )
{
//
// #ifdef BUILD_DX
// m_ErrorExtra = DXGetErrorString9 ( result );
// #endif
OutputMessage ();
m_ErrorExtra = "";
}
void CError::PrintErrGL ( std::string err, int result )
{
OutputMessage ();
m_ErrorExtra = "";
}
void CError::PrintErrW ( std::string err, int result )
{
OutputMessage ();
m_ErrorExtra = "";
}
/*
void CError::GetErrorMessage ( ErrorDef::Errors err )
{
switch (err) {
//----------------------------------------------------- MATRIX Errors
case ErrorDef::MatrixIsNull:
m_strDescription = "Matrix data is null\n";
m_strFunction = "Matrix::op()";
m_strFix = "";
break;
case ErrorDef::ColOutOfBounds:
m_strDescription = "Column index out of bounds\n";
m_strFunction = "Matrix::op()";
m_strFix = "";
break;
case ErrorDef::RowOutOfBounds:
m_strDescription = "Row index out of bounds\n";
m_strFunction = "Matrix::op()";
m_strFix = "";
break;
//----------------------------------------------------- WinDX Errors
case ErrorDef::DXInitFail:
m_strDescription = "Initialization of DirectX failed.";
m_strFunction = "GameX::InitDirect3D";
m_strFix = "Reinstall DirectX 9.0. Confirm DirectX hardware support.";
break;
case ErrorDef::DXCannotGetMode:
m_strDescription = "Cannot get current display mode.";
m_strFunction = "GameX::SysGetCurrentMode";
m_strFix = "";
break;
case ErrorDef::DXCannotSetMode:
m_strDescription = "Cannot select display mode.";
m_strFunction = "GameX::SysSelectMode";
m_strFix = "Try requesting a different display mode and options.";
break;
case ErrorDef::WinCannotCreateClass:
m_strDescription = "Cannot create Windows class.";
m_strFunction = "GameX::SysCreateWindowsClass";
m_strFix = "Close other applications. Restart system.";
break;
case ErrorDef::WinCannotCreateWindow:
m_strDescription = "Cannot create Window.";
m_strFunction = "GameX::SysCreateWindow";
m_strFix = "Try requesting a different display mode and options.\nClose other applications. Restart system. Possibly unsupported display hardware.";
break;
case ErrorDef::DXCannotCreateDevice:
m_strDescription = "Cannot create DirectX Device.";
m_strFunction = "GameX::SysCreateDevice3D";
m_strFix = "Try requesting a different display mode and options.";
break;
case ErrorDef::DXCannotCreateDepthStencils:
m_strDescription = "Cannot create DirectX Depth Stencils.";
m_strFunction = "GameX::SysCreateDepthStencils";
m_strFix = "Try requesting a different display mode and options.";
break;
//---------------------------------------------------------------- File Errors
case ErrorDef::CannotAppendAndRead:
m_strDescription = "Cannot open a file in both APPEND and READ mode.";
m_strFunction = "File::Open";
m_strFix = "Use either APPEND, READ or WRITE when opening file.";
break;
case ErrorDef::CannotAppendAndWrite:
m_strDescription = "Cannot open a file in both APPEND and WRITE mode.";
m_strFunction = "File::Open";
m_strFix = "Use either APPEND, READ or WRITE when opening file.";
break;
case ErrorDef::FileNotFound:
m_strDescription = "File not found.";
m_strFunction = "File::Open";
m_strFix = "Use AUTOCREATE if you would like to create a new file.";
break;
case ErrorDef::LeaveEofOnlyOnAppend:
m_strDescription = "Warning:LEAVEEOF flag can only be used in APPEND mode.";
m_strFunction = "File::Open";
m_strFix = "Remove the LEAVEEOF flag or open file in APPEND mode.";
break;
case ErrorDef::NoModeSpecified:
m_strDescription = "No open mode specified.";
m_strFunction = "File::Open";
m_strFix = "You must specify READ, WRITE or APPEND to open a file.";
break;
case ErrorDef::NoNotOpenCmd:
m_strDescription = "NOTOPEN cannot be used as an open file flag.";
m_strFunction = "File::Open";
m_strFix = "Remove the NOTOPEN flag.";
break;
case ErrorDef::NoSeqAndRandom:
m_strDescription = "Cannot open file in both SEQUENTIAL and RANDOM access modes.";
m_strFunction = "File::Open";
m_strFix = "Choose either SEQUENTIAL or RANDOM mode to open file in.";
break;
case ErrorDef::CannotCreateFont:
m_strDescription = "Cannot create default font.";
m_strFunction = "RenderDX::Initialize";
m_strFix = "DirectX fonts are not supported for some reason.";
break;
case ErrorDef::CannotCreateSprite:
m_strDescription = "Cannot create default sprite.";
m_strFunction = "RenderDX::Initialize";
m_strFix = "DirectX sprites are not supported for some reason.";
break;
case ErrorDef::CannotAddImage:
m_strDescription = "Cannot create image on video memory.";
m_strFunction = "RenderDX::AddImage";
m_strFix = "DirectX was unable to create hardware texture for the image.";
break;
case ErrorDef::CannotUpdateImage:
m_strDescription = "Cannot update image data on video memory.";
m_strFunction = "RenderDX::UpdateImage";
m_strFix = "DirectX was unable to modify hardware texture for the image.";
break;
case ErrorDef::CannotOpenFile:
#if defined(BUILD_VSNET)
m_strDescription = strerror( errno );
#else
m_strDescription = ""; // should replace with Mac general error code
#endif
m_strFunction = "File::Open";
m_strFix = "";
break;
case ErrorDef::ImageLoadError:
m_strDescription = "Unable to load image.";
m_strFunction = "ImageX::Load";
m_strFix = "";
break;
default:
char msg[500];
sprintf (msg, "%d", (int) err );
m_strDescription = "Undefined error: ";
m_strDescription += msg;
m_strSubsystem = "Undefined error.";
m_strFix = "Error must be given a description and fix message.";
break;
};
}
*/
#ifdef MEMORY_DEBUG
// User-defined operator new.
void *operator new( size_t stSize )
{
void* pvMem = malloc( stSize );
debug.Printf ( "NEW %p (%d bytes)\n", pvMem, stSize );
return pvMem;
}
// User-defined operator delete.
void operator delete( void *pvMem )
{
debug.Printf ( "DELETE %p\n", pvMem );
free ( pvMem );
}
#endif

138
Extras/sph/common/mdebug.h Normal file
View File

@@ -0,0 +1,138 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef INC_MINT_DEBUG_H
#define INC_MINT_DEBUG_H
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#ifdef BUILD_VS2005
// #pragma warning( disable : 4101) // removes warning 4101 - unreferenced local
// #pragma warning( disable : 4244) // removes warning 4244 - conversion loss of data
#pragma warning( disable : 4995) // removes warning 4995 - depricated function
#pragma warning( disable : 4996) // removes warning 4996 - depricated function
// #pragma warning( disable : 4018) // removes warning 4018 - unsigned/signed
#endif
class CDebug {
public:
CDebug ();
~CDebug ();
// Control functions
void Start ();
void Stop ();
void SendToConsole ( bool tf );
void SendToSysbox ( bool tf );
void SendToFile ( bool tf );
void SendToFile ( char *filename );
// Output functions
void Exit ( int code );
void Print ( std::string subsys, std::string msg );
void Print ( std::string msg );
void Print ( char* msg);
void PrintF ( std::string subsys, char *msg, ... );
void Printf ( char *msg, ... );
void PrintErr ( std::string errid, std::string subsys, std::string msg, std::string sysbox ); // Used by Error class
// Filtering functions
void AddFilter ( std::string subsys );
void ClearFilters ();
private:
bool m_bStarted;
bool m_bToFile;
bool m_bToCons;
bool m_bToSysbox;
std::string m_OutName;
FILE* m_OutFile;
FILE* m_OutCons;
std::map< std::string, bool > m_Filters;
};
class CErrorMsg {
std::string m_strSubsys;
std::string m_strFunction;
std::string m_strMessage;
std::string m_strFix;
std::string m_strExtraInfo;
bool m_bFatal;
bool m_bFilter;
};
class CError {
public:
CError ();
void Start ();
void Start ( char* fname );
void LoadErrors ();
void OutputMessage ();
void Exit () { Exit (EXIT_SUCCESS); }
void Exit ( int code );
// Unregistered errors
void Print ( std::string subsys, std::string msg );
void Print ( std::string msg );
void Print ( char* msg);
void PrintF ( std::string subsys, char *msg, ... );
// Registered errors
void PrintErr ( std::string err );
void PrintErrDX ( std::string err, int result ); // for DirectX errors
void PrintErrGL ( std::string err, int result ); // for OpenGL errors
void PrintErrW ( std::string err, int result ); // for Windows errors
std::string GetErrorSubsys () { return m_ErrorID; }
std::string GetErrorMessage () { return m_ErrorMsg; }
std::string GetErrorFunction () { return m_ErrorFunc; }
std::string GetErrorFix () { return m_ErrorFix; }
std::string GetErrorExtra () { return m_ErrorExtra; }
private:
bool m_bStarted;
std::string m_ErrorID; // Current error
std::string m_ErrorSubsys;
std::string m_ErrorMsg;
std::string m_ErrorFunc;
std::string m_ErrorFix;
std::string m_ErrorExtra;
bool m_bFatal;
std::map < std::string, CErrorMsg* > m_Errors; // List of registered errors
};
extern CError error;
extern CDebug debug;
#endif

955
Extras/sph/common/mesh.cpp Normal file
View File

@@ -0,0 +1,955 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <conio.h>
#include <vector.h>
#include "mesh.h"
#include "mdebug.h"
//#include "mfile.h"
//#include "event.h"
#include <gl/glut.h>
#define DEGtoRAD (3.141592/180.0)
bool Mesh::mbInitStatic = false;
int Mesh::miBufSize[MAX_MFORMAT][MAX_BFORMAT];
Mesh::Mesh ()
{
debug.SendToConsole ( true );
m_Mform = MFormat::UDef;
m_CurrF = 0;
m_Vbuf = BUF_UNDEF;
m_Ebuf = BUF_UNDEF;
m_Fbuf = BUF_UNDEF;
}
Mesh& Mesh::operator= ( Mesh& src )
{
CopyBuffers ( src );
CopyAttributes ( src );
m_Mform = src.GetMeshBufs ( m_Vbuf, m_Ebuf, m_Fbuf );
return *this;
}
void Mesh::InitStatic ()
{
mbInitStatic = true;
miBufSize[ (int) FVF ][ (int) BVert ] = sizeof ( VertFVF );
miBufSize[ (int) FVF ][ (int) BFace ] = sizeof ( FaceFVF );
miBufSize[ (int) FVF ][ (int) BEdge ] = 0;
miBufSize[ (int) CM ][ (int) BVert ] = sizeof ( VertCM );
miBufSize[ (int) CM ][ (int) BEdge ] = sizeof ( EdgeCM );
miBufSize[ (int) CM ][ (int) BFace ] = sizeof ( FaceCM );
}
/*void Mesh::onUpdate ( objData dat, mint::Event* e )
{
uchar dtype;
hval num;
hval max;
long size;
ushort stride;
int num_buf;
switch ( dat ) {
case 'full':
ClearBuffers ();
ClearAttributes ();
m_Mform = (MFormat) e->getUChar ();
m_Vbuf = e->getUChar ();
m_Ebuf = e->getUChar ();
m_Fbuf = e->getUChar ();
num_buf = e->getInt ();
for (int b=0; b < num_buf; b++) {
dtype = e->getUChar ();
stride = e->getUShort ();
num = e->getInt ();
max = e->getInt ();
AddBuffer ( dtype, stride, max );
e->getMem ( mBuf[b].data, num * mBuf[b].stride );
mBuf[b].num = num;
}
mHeapNum = e->getInt ();
mHeapMax = e->getInt ();
mHeapFree = e->getInt ();
mHeap = new hval[mHeapMax];
e->getMem ( (char*) mHeap, mHeapNum * sizeof(hval) );
break;
};
}
void Mesh::UpdateMesh ()
{
int s = GetSize () + (mBuf.size()+1)*4*sizeof(int);
mint::Event* e = updateStart ( 'full', s );
e->attachUChar ( (char) m_Mform ) ;
e->attachUChar ( (char) m_Vbuf );
e->attachUChar ( (char) m_Ebuf );
e->attachUChar ( (char) m_Fbuf );
e->attachInt ( mBuf.size() );
for (int b=0; b < mBuf.size(); b++) {
e->attachUChar ( mBuf[b].dtype );
e->attachUShort ( mBuf[b].stride );
e->attachInt ( mBuf[b].num );
e->attachInt ( mBuf[b].max );
e->attachMem ( mBuf[b].data, mBuf[b].num * mBuf[b].stride );
}
e->attachInt ( mHeapNum );
e->attachInt ( mHeapMax );
e->attachInt ( mHeapFree );
e->attachMem ( (char*) mHeap, mHeapNum * sizeof(hval) );
updateEnd ( e );
}
*/
//------------------------------------------------------------------ FVF - Face-vertex-face Mesh
void Mesh::CreateFVF ()
{
if ( !mbInitStatic ) InitStatic ();
SetFuncFVF ();
m_Mform = FVF;
m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( FVF, BVert ), 64 );
m_Fbuf = AddBuffer ( (uchar) BFace, BufSize( FVF, BFace ), 64 );
AddAttribute ( m_Vbuf, "pos", sizeof ( AttrPos ), false );
AddAttribute ( m_Vbuf, "norm", sizeof ( AttrNorm ) );
AddHeap ( 128 );
}
void Mesh::ClearFVF ()
{
ResetBuffer ( 0, mBuf[0].max );
ResetBuffer ( 1, mBuf[0].max );
ResetHeap ();
}
void Mesh::SmoothFVF ( int iter )
{
Vector3DF norm, side;
int cnt;
FaceFVF* f;
VertFVF *v1, *v2, *v3;
AttrPos* face_pos;
face_pos = new AttrPos[ NumFace() ];
for (int j=0; j < iter; j++) {
// Compute centroid of all faces
for (int n=0; n < NumFace(); n++) {
f = GetFaceFVF ( n );
v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3);
face_pos[n].x = ( v1->x + v2->x + v3->x ) / 3.0;
face_pos[n].y = ( v1->y + v2->y + v3->y ) / 3.0;
face_pos[n].z = ( v1->z + v2->z + v3->z ) / 3.0;
}
// Compute new vertex positions
int cnt;
Vector3DF vec;
for (int n=0; n < NumVert(); n++) {
v1 = GetVertFVF ( n );
vec.Set (0,0,0);
hval* fptr = mHeap + v1->flist.pos;
for (int j=0; j < v1->flist.cnt; j++) {
vec.x += face_pos[ (*fptr) ].x;
vec.y += face_pos[ (*fptr) ].y;
vec.z += face_pos[ (*fptr) ].z;
fptr++;
}
v1->x = vec.x / (float) v1->flist.cnt;
v1->y = vec.y / (float) v1->flist.cnt;
v1->z = vec.z / (float) v1->flist.cnt;
}
}
delete face_pos;
}
void Mesh::SetNormalFVF ( int n, Vector3DF norm )
{
VertFVF* v1;
AttrNorm* vn;
int noff = GetAttrOffset ( "norm" );
v1 = GetVertFVF ( n );
vn = (AttrNorm* ) ((char*) v1 + noff );
vn->nx = norm.x;
vn->ny = norm.y;
vn->nz = norm.z;
}
void Mesh::SetColorFVF ( int n, DWORD clr )
{
VertFVF* v1;
AttrClr* vc;
int coff = GetAttrOffset ( "color" );
if ( coff == -1 ) return;
v1 = GetVertFVF ( n );
vc = (AttrClr* ) ((char*) v1 + coff );
vc->clr = clr;
}
void Mesh::ComputeNormalsFVF ()
{
Vector3DF norm, side;
FaceFVF* f;
VertFVF *v1, *v2, *v3, *v4;
AttrNorm* vn;
AttrNorm* face_norms;
face_norms = new AttrNorm[ NumFace() ];
// Clear vertex normals
int noff = GetAttrOffset ( "norm" );
for (int n=0; n < NumVert(); n++) {
v1 = GetVertFVF ( n );
vn = (AttrNorm*) ((char*) v1 + noff);
vn->nx = 0;
vn->ny = 0;
vn->nz = 0;
}
// Compute normals of all faces
for (int n=0; n < NumFace(); n++) {
f = GetFaceFVF ( n );
v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3);
side = Vector3DF ( v2->x, v2->y, v2->z );
side -= Vector3DF ( v1->x, v1->y, v1->z );
side.Normalize ();
norm = Vector3DF ( v3->x, v3->y, v3->z );
norm -= Vector3DF ( v1->x, v1->y, v1->z );
norm.Normalize ();
norm.Cross ( side );
face_norms[n].nx = norm.x;
face_norms[n].ny = norm.y;
face_norms[n].nz = norm.z;
vn = (AttrNorm*) ((char*) v1 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z;
vn = (AttrNorm*) ((char*) v2 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z;
vn = (AttrNorm*) ((char*) v3 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z;
if ( f->v4 != -1 ) {
v4 = GetVertFVF(f->v4);
vn = (AttrNorm*) ((char*) v4 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z;
}
}
// Normalize vertex normals
Vector3DF vec;
for (int n=0; n < NumVert(); n++) {
v1 = GetVertFVF ( n );
vn = (AttrNorm*) ((char*) v1 + noff);
vec.Set ( vn->nx, vn->ny, vn->nz );
vec.Normalize ();
vn->nx = vec.x;
vn->ny = vec.y;
vn->nz = vec.z;
}
// Compute normal of a vertex from surrounding faces (slow method)
/*int cnt;
for (int n=0; n < NumVert(); n++) {
v1 = GetVertFVF ( n );
vn = (VertNorm*) GetExtraFVF ( v1 );
cnt = 0;
vn->nx = 0; vn->ny = 0; vn->nz = 0;
hval* fptr = mHeap + v1->flist.pos;
for (int j=0; j < v1->flist.cnt; j++) {
vn->nx += face_norms[ (*fptr) ].nx;
vn->ny += face_norms[ (*fptr) ].ny;
vn->nz += face_norms[ (*fptr) ].nz;
cnt++;
fptr++;
}
vn->nx /= (float) cnt;
vn->ny /= (float) cnt;
vn->nz /= (float) cnt;
}*/
delete face_norms;
}
void Mesh::SetFuncFVF ()
{
m_AddVertFunc = &Mesh::AddVertFVF;
m_AddFaceFast3Func = &Mesh::AddFaceFast3FVF;
m_AddFaceFast4Func = &Mesh::AddFaceFast4FVF;
}
xref Mesh::AddFaceFast3FVF ( xref v1, xref v2, xref v3 )
{
xref fNdx;
FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx );
f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = -1;
AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA );
return fNdx;
}
xref Mesh::AddFaceFast4FVF ( xref v1, xref v2, xref v3, xref v4 )
{
xref fNdx;
FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx );
f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = v4;
AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertFVF(v4)->flist, FACE_DELTA );
return fNdx;
}
xref Mesh::AddVertFVF ( float x, float y, float z )
{
xref ndx;
VertFVF* v = (VertFVF*) AddElem ( m_Vbuf, ndx );
v->x = x; v->y = y; v->z = z;
ClearRefs ( v->flist );
return ndx;
}
void Mesh::DebugFVF ()
{
int n;
int j;
VertFVF* v;
FaceFVF* f;
debug.Printf ( "-- MESH --\n");
debug.Printf ( "-- verts\n" );
for (n=0; n < NumVert(); n++) {
v = GetVertFVF(n);
debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) f:%d %d{", n, v->x, v->y, v->z, v->flist.cnt, v->flist.pos);
if ( v->flist.cnt > 0 ) {
for (j=0; j < v->flist.cnt; j++)
debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA );
}
debug.Printf ( "}\n" );
}
debug.Printf ( "-- faces\n" );
for (n=0; n < NumFace(); n++) {
f = GetFaceFVF(n);
debug.Printf ( "%d: v:%d %d %d\n", n, f->v1, f->v2, f->v3);
}
DebugHeap ();
debug.Printf ("\n\n");
//_getch();
}
//------------------------------------------------------------------ CM - Connected Mesh
// Create Connected Mesh (CM)
void Mesh::CreateCM ()
{
if ( !mbInitStatic ) InitStatic ();
SetFuncCM ();
m_Mform = CM;
m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( CM, BVert ), 64 );
m_Ebuf = AddBuffer ( (uchar) BEdge, BufSize ( CM, BEdge), 64 );
m_Fbuf = AddBuffer ( (uchar) BFace, BufSize ( CM, BFace), 64 );
AddAttribute ( m_Vbuf, "pos", sizeof(AttrPos), false );
AddAttribute ( m_Vbuf, "norm", sizeof(AttrNorm) );
AddHeap ( 128 );
}
void Mesh::SetFuncCM ()
{
m_AddVertFunc = &Mesh::AddVertCM;
m_AddFaceFast3Func = &Mesh::AddFaceFast3CM;
m_AddFaceFast4Func = &Mesh::AddFaceFast4CM;
}
xref Mesh::AddVertCM ( float x, float y, float z )
{
xref ndx;
VertCM* v = (VertCM*) AddElem ( m_Vbuf, ndx );
v->x = x; v->y = y; v->z = z;
ClearRefs ( v->elist );
ClearRefs ( v->flist );
return ndx;
}
xref Mesh::AddFaceFast3CM ( xref v1, xref v2, xref v3 )
{
xref fNdx;
FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx );
f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = -1;
xref eNdx;
eNdx = AddEdgeCM ( f->v1, f->v2 ); f->e1 = eNdx;
eNdx = AddEdgeCM ( f->v2, f->v3 ); f->e2 = eNdx;
eNdx = AddEdgeCM ( f->v3, f->v1 ); f->e3 = eNdx;
AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA );
return fNdx;
}
xref Mesh::AddFaceFast4CM ( xref v1, xref v2, xref v3, xref v4 )
{
xref fNdx;
FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx );
f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = v4;
xref eNdx;
eNdx = AddEdgeCM ( f->v1, f->v2 ); f->e1 = eNdx;
eNdx = AddEdgeCM ( f->v2, f->v3 ); f->e2 = eNdx;
eNdx = AddEdgeCM ( f->v3, f->v4 ); f->e3 = eNdx;
eNdx = AddEdgeCM ( f->v4, f->v1 ); f->e4 = eNdx;
AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA );
AddRef ( fNdx, GetVertCM(v4)->flist, FACE_DELTA );
return fNdx;
}
xref Mesh::FindEdgeCM ( xref v1, xref v2 )
{
EdgeCM *pE;
VertCM *pV1;
pV1 = GetVertCM(v1);
if ( pV1->elist.cnt == 0 ) return -1;
hval* e = mHeap + pV1->elist.pos;
#ifdef MESH_DEBUG
for (int n=0; n < pV1->elist.cnt; n++) {
pE = GetEdgeCM( (*e)-EDGE_DELTA );
if ( pE->v1 == v2 || pE->v2 == v2 ) return (*e)-EDGE_DELTA;
e++;
}
#else
for (int n=0; n < pV1->elist.cnt; n++) {
pE = GetEdgeCM( *e );
if ( pE->v1 == v2 || pE->v2 == v2 ) return *e;
e++;
}
#endif
return -1;
}
xref Mesh::AddEdgeCM ( xref v1, xref v2 )
{
xref eNdx = FindEdgeCM ( v1, v2 );
EdgeCM* e = GetEdgeCM(eNdx);
if ( eNdx == -1 ) {
e = (EdgeCM*) AddElem ( m_Ebuf, eNdx );
e->f1 = 0;
e->f2 = 0;
e->v1 = v1;
e->v2 = v2;
AddRef ( eNdx, GetVertCM(v1)->elist, EDGE_DELTA );
AddRef ( eNdx, GetVertCM(v2)->elist, EDGE_DELTA );
}
return eNdx;
}
void Mesh::DebugCM ()
{
int n;
int j;
VertCM* v;
EdgeCM* e;
FaceCM* f;
debug.Printf ( "-- MESH --\n");
debug.Printf ( "-- verts\n" );
for (n=0; n < NumVert(); n++) {
v = GetVertCM(n);
debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) e:%d %d{", n, v->x, v->y, v->z, v->elist.cnt, v->elist.pos);
if ( v->elist.cnt > 0 ) {
for (j=0; j < v->elist.cnt; j++)
debug.Printf ( "%d ", *(mHeap+v->elist.pos+j) - EDGE_DELTA );
}
debug.Printf ( "}, f:%d %d{", v->flist.cnt, v->flist.pos);
if ( v->flist.cnt > 0 ) {
for (j=0; j < v->flist.cnt; j++)
debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA );
}
debug.Printf ( "}\n" );
}
debug.Printf ( "-- edges\n" );
for (n=0; n < NumEdge(); n++) {
e = GetEdgeCM (n);
debug.Printf ( "%d: v:%d %d, f:%d %d\n", n, e->v1, e->v2, e->f1, e->f2 );
}
debug.Printf ( "-- faces\n" );
for (n=0; n < NumFace(); n++) {
f = GetFaceCM(n);
debug.Printf ( "%d: v:%d %d %d, e:%d %d %d\n", n, f->v1, f->v2, f->v3, f->e1, f->e2, f->e3 );
}
hval* pVal = mHeap;
debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree );
for (n=0; n < mHeapNum; n++) {
if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n );
#ifdef MESH_DEBUG
if ( *pVal == 0 ) {
debug.Printf ( "00000 ");
} else if ( *pVal == (hval) 0xFFFF ) {
debug.Printf ( "----- ");
} else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) {
debug.Printf ( "v%04d ", *pVal - VERT_DELTA );
} else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) {
debug.Printf ( "e%04d ", *pVal - EDGE_DELTA );
} else if ( *pVal >= FACE_DELTA ) {
debug.Printf ( "f%04d ", *pVal - FACE_DELTA );
} else {
debug.Printf ( "H%04d ", (int) *pVal );
}
#else
debug.Printf ( "%05d ", (int) *pVal );
#endif
pVal++;
}
debug.Printf ("\n\n");
//_getch();
}
void Mesh::DebugHeap ()
{
hval* pVal = mHeap;
debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree );
for (int n=0; n < mHeapNum; n++) {
if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n );
#ifdef MESH_DEBUG
if ( *pVal == 0 ) {
debug.Printf ( "00000 ");
} else if ( *pVal == (hval) 0xFFFF ) {
debug.Printf ( "----- ");
} else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) {
debug.Printf ( "v%04d ", *pVal - VERT_DELTA );
} else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) {
debug.Printf ( "e%04d ", *pVal - EDGE_DELTA );
} else if ( *pVal >= FACE_DELTA ) {
debug.Printf ( "f%04d ", *pVal - FACE_DELTA );
} else {
debug.Printf ( "H%04d ", (int) *pVal );
}
#else
debug.Printf ( "%05d ", (int) *pVal );
#endif
pVal++;
}
}
void Mesh::DrawVertsCM ( float* viewmat, int a, int b )
{
VertCM* v;
glColor3f (1,0,0);
glLoadMatrixf ( viewmat );
glTranslatef ( mT.x, mT.y, mT.z );
glBegin ( GL_POINTS );
for (int n = a; n <= b; n++) {
v = GetVertCM (n);
glVertex3f ( v->x, v->y, v->z );
//glCallList ( m_GLObj );
}
glEnd ();
}
void Mesh::DrawVertsFVF ( float* viewmat, int a, int b )
{
VertFVF* v;
glColor3f (1,0,0);
glLoadMatrixf ( viewmat );
glTranslatef ( mT.x, mT.y, mT.z );
glBegin ( GL_POINTS );
for (int n = a; n <= b; n++) {
v = GetVertFVF (n);
glVertex3f ( v->x, v->y, v->z );
//glCallList ( m_GLObj );
}
glEnd ();
}
void Mesh::DrawFacesCM ( float* viewmat, int a, int b )
{
FaceCM* f;
VertCM* v;
AttrNorm* vn;
int noff = GetAttrOffset ( "norm" );
glLoadMatrixf ( viewmat );
glTranslatef ( mT.x, mT.y, mT.z );
GLenum dm = GL_TRIANGLES;
glBegin ( dm );
f = GetFaceCM ( a );
for (int n = a; n <= b; n++) {
if ( f->v4 == -1 ) {
if ( dm != GL_TRIANGLES ) { glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; }
v = GetVertCM(f->v1); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertCM(f->v2); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertCM(f->v3); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
} else {
if ( dm != GL_QUADS ) { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; }
v = GetVertCM(f->v1); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertCM(f->v2); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertCM(f->v3); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertCM(f->v4); vn = (AttrNorm*) ((char*) v + noff);
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
}
f++;
}
glEnd ();
}
void Mesh::DrawFacesFVF ( float* viewmat, int a, int b )
{
FaceFVF* f;
VertFVF* v;
AttrNorm* vn;
AttrClr* vc;
int noff = GetAttrOffset ( "norm" );
int coff = GetAttrOffset ( "color" );
coff = -1;
//glLoadMatrixf ( viewmat );
//glTranslatef ( mT.x, mT.y, mT.z );
GLenum dm = GL_TRIANGLES;
glBegin ( dm );
f = GetFaceFVF ( a );
for (int n = a; n <= b; n++) {
if ( f->v4 == -1 ) {
if ( dm != GL_TRIANGLES ) { glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; }
v = GetVertFVF(f->v1); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertFVF(f->v2); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertFVF(f->v3); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
} else {
if ( dm != GL_QUADS ) { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; }
v = GetVertFVF(f->v1); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertFVF(f->v2); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertFVF(f->v3); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
v = GetVertFVF(f->v4); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff);
if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z );
}
f++;
}
glEnd ();
}
void Mesh::DrawEdgesCM ( float* viewmat, int a, int b )
{
EdgeCM* e;
glLoadMatrixf ( viewmat );
glTranslatef ( mT.x, mT.y, mT.z );
glBegin ( GL_LINES );
e = GetEdgeCM ( a );
for (int n = a; n <= b; n++) {
glVertex3f ( GetVertCM(e->v1)->x, GetVertCM(e->v1)->y, GetVertCM(e->v1)->z );
glVertex3f ( GetVertCM(e->v2)->x, GetVertCM(e->v2)->y, GetVertCM(e->v2)->z );
e++;
}
glEnd ();
}
void Mesh::DrawGL ( float* viewmat )
{
mT.Set(0,0,0);
switch ( m_Mform ) {
case CM: {
glDepthRange (0.001, 1.001);
//glColor3f ( 1, 0, 0 ); DrawVertsCM ( viewmat, 0, NumVert()-1 );
glColor3f ( .6, .6, .6 ); DrawFacesCM ( viewmat, 0, NumFace()-1 );
//glDepthRange (0.0005, 1.0005);
//glColor3f ( 1, 1, 1); DrawEdgesCM ( viewmat, 0, NumEdge()-1 );
} break;
case FVF: {
//glColor3f (1,0,0); DrawVertsFVF ( viewmat, 0, NumVert()-1 );
//glEnable (GL_LIGHTING);
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
glColor4f ( .9, .9, .9, 0.75 ); DrawFacesFVF ( viewmat, 0, NumFace()-1 );
/*glDisable (GL_LIGHTING );
glDepthRange (0.000, 1.00);
glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
glLineWidth ( 3 );
glColor4f ( 0, 0, 0, 1.0 ); DrawFacesFVF ( viewmat, 0, NumFace()-1 );
glEnable ( GL_LIGHTING );
glLineWidth ( 1);
glDepthRange (0.0, 1.0);
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );*/
} break;
}
}
void Mesh::DrawFaceGL ( float* viewmat )
{
mT.Set (0,0,0);
if ( m_CurrF < 0 ) m_CurrF = NumFace()-1;
if ( m_CurrF >= NumFace() ) m_CurrF = 0;
switch ( m_Mform ) {
case FVF:
glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 );
DrawFacesFVF ( viewmat, m_CurrF, m_CurrF );
break;
case CM:
glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 );
DrawFacesCM ( viewmat, m_CurrF, m_CurrF );
break;
};
}
void Mesh::Measure ()
{
hval* pCurr = mHeap + mHeapFree;
int vs, es, fs, hs, hm, as, frees = 0;
vs = NumVert(); if ( vs !=0 ) vs *= GetStride(m_Vbuf);
es = NumEdge(); if ( es !=0 ) es *= GetStride(m_Ebuf);
fs = NumFace(); if ( fs !=0 ) fs *= GetStride(m_Fbuf);
hs = mHeapNum*sizeof(hval);
hm = mHeapMax*sizeof(hval);
while ( pCurr != mHeap-1 ) {
frees += *(pCurr);
pCurr = mHeap + * (hpos*) (pCurr + FPOS);
}
frees *= sizeof(hval);
as = 0;
if ( m_Vbuf!=-1 ) as += mBuf[m_Vbuf].max * GetStride(m_Vbuf);
if ( m_Fbuf!=-1 ) as += mBuf[m_Fbuf].max * GetStride(m_Fbuf);
if ( m_Ebuf!=-1 ) as += mBuf[m_Ebuf].max * GetStride(m_Ebuf);
as += hm;
debug.Printf ( "NumVert: %07.1fk (%d)\n", vs/1000.0, NumVert() );
debug.Printf ( "NumFace: %07.1fk (%d)\n", fs/1000.0, NumFace() );
debug.Printf ( "NumEdge: %07.1fk (%d)\n", es/1000.0, NumEdge() );
debug.Printf ( "Heap Size: %07.1fk (%d)\n", hs/1000.0, mHeapNum );
debug.Printf ( "Free Size: %07.1fk\n", frees/1000.0 );
debug.Printf ( "Heap Used: %07.1fk (%5.1f%%)\n", (hs-frees)/1000.0, (hs-frees)*100.0/(vs+es+fs+hs-frees) );
debug.Printf ( "Heap Max: %07.1fk\n", hm/1000.0 );
debug.Printf ( "Total Used: %07.1fk\n", (vs+es+fs+hs-frees)/1000.0 );
debug.Printf ( "Total Alloc: %07.1fk\n", as/1000.0 );
debug.Printf ( "Fragmentation: %f%%\n", (hm-(hs-frees))*100.0 / hm );
}
/*int Mesh::GetIndex ( int b, void* v )
{
if ( v == 0x0 ) return -1;
return ((char*) v - (char*) mBuf[b].data) / mBuf[b].stride;
}*/
int Mesh::FindPlyElem ( char typ )
{
for (int n=0; n < m_Ply.size(); n++) {
if ( m_Ply[n]->type == typ ) return n;
}
return -1;
}
int Mesh::FindPlyProp ( int elem, std::string name )
{
for (int n=0; n < m_Ply[elem]->prop_list.size(); n++) {
if ( m_Ply[elem]->prop_list[n].name.compare ( name)==0 )
return n;
}
return -1;
}
void Mesh::LoadPly ( char* fname, float s )
{
/* int m_PlyCnt;
float m_PlyData[40];
char buf[1000];
char bword[1000];
std::string word;
Buffer b(1000);
int vnum, fnum, elem, cnt;
char typ;
if ( m_Mform == MFormat::UDef )
CreateFVF ();
m_File.Open ( fname, FILE_READ | FILE_SEQUENTIAL );
if ( !m_File.Valid() ) {
error.PrintF ( "mesh", "Could not find file: %s\n", fname );
error.Exit ();
}
// Read header
m_File.ReadLine ( buf, 1000 );
b.ReadWord ( buf, bword ); word = bword;
if ( word.compare("ply" )!=0 ) {
error.PrintF ( "Not a ply file. %s\n", fname );
error.Exit ();
}
debug.Printf ( "Reading PLY.\n" );
while ( m_File.ReadLine ( buf, 1000 ) == FILE_STATUS_OK ) {
b.ReadWord ( buf, bword );
word = bword;
if ( word.compare("comment" )!=0 ) {
if ( word.compare("end_header")==0 ) break;
if ( word.compare("property")==0 ) {
b.ReadWord ( buf, bword );
word = bword;
if ( word.compare("float")==0 ) typ = PLY_FLOAT;
if ( word.compare("float16")==0 ) typ = PLY_FLOAT;
if ( word.compare("float32")==0 ) typ = PLY_FLOAT;
if ( word.compare("int8")==0 ) typ = PLY_INT;
if ( word.compare("uint8")==0 ) typ = PLY_UINT;
if ( word.compare("list")==0) {
typ = PLY_LIST;
b.ReadWord ( buf, bword );
b.ReadWord ( buf, bword );
}
b.ReadWord ( buf, bword );
word = bword;
AddPlyProperty ( typ, word );
}
if ( word.compare("element" )==0 ) {
b.ReadWord ( buf, bword); word = bword;
if ( word.compare("vertex")==0 ) {
b.ReadWord ( buf, bword);
vnum = atoi ( bword );
debug.Printf ( " Verts: %d\n", vnum );
AddPlyElement ( PLY_VERTS, vnum );
}
if ( word.compare("face")==0 ) {
b.ReadWord ( buf, bword);
fnum = atoi ( bword );
debug.Printf ( " Faces: %d\n", fnum );
AddPlyElement ( PLY_FACES, fnum );
}
}
}
}
// Read data
int xi, yi, zi;
debug.Printf ( " Reading verts..\n" );
elem = FindPlyElem ( PLY_VERTS );
xi = FindPlyProp ( elem, "x" );
yi = FindPlyProp ( elem, "y" );
zi = FindPlyProp ( elem, "z" );
if ( elem == -1 || xi == -1 || yi == -1 || zi == -1 ) {
debug.Printf ( "ERROR: Vertex data not found.\n" );
exit(-1);
}
for (int n=0; n < m_Ply[elem]->num; n++) {
m_File.ReadLine ( buf, 1000 );
for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) {
b.ReadWord ( buf, bword );
m_PlyData[ j ] = atof ( bword );
}
AddVert ( m_PlyData[xi]*s, m_PlyData[zi]*s, m_PlyData[yi]*s );
}
debug.Printf ( " Reading faces..\n" );
elem = FindPlyElem ( PLY_FACES );
xi = FindPlyProp ( elem, "vertex_indices" );
if ( elem == -1 || xi == -1 ) {
debug.Printf ( "ERROR: Face data not found.\n" );
exit(-1);
}
for (int n=0; n < m_Ply[elem]->num; n++) {
m_File.ReadLine ( buf, 1000 );
m_PlyCnt = 0;
for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) {
if ( m_Ply[elem]->prop_list[j].type == PLY_LIST ) {
b.ReadWord ( buf, bword );
cnt = atoi ( bword );
m_PlyData[ m_PlyCnt++ ] = cnt;
for (int c =0; c < cnt; c++) {
b.ReadWord ( buf, bword );
m_PlyData[ m_PlyCnt++ ] = atof ( bword );
}
} else {
b.ReadWord ( buf, bword );
m_PlyData[ m_PlyCnt++ ] = atof ( bword );
}
}
if ( m_PlyData[xi] == 3 ) {
//debug.Printf ( " Face: %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] );
AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] );
}
if ( m_PlyData[xi] == 4 ) {
//debug.Printf ( " Face: %d, %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4]);
AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4] );
}
}
Measure ();
ComputeNormalsFVF (); // !-- should be abstracted
*/
// UpdateMesh ();
}
void Mesh::AddPlyElement ( char typ, int n )
{
debug.Printf ( " Element: %d, %d\n", typ, n );
PlyElement* p = new PlyElement;
p->num = n;
p->type = typ;
p->prop_list.clear ();
m_PlyCurrElem = m_Ply.size();
m_Ply.push_back ( p );
}
void Mesh::AddPlyProperty ( char typ, std::string name )
{
debug.Printf ( " Property: %d, %s\n", typ, name.c_str() );
PlyProperty p;
p.name = name;
p.type = typ;
m_Ply [ m_PlyCurrElem ]->prop_list.push_back ( p );
}

160
Extras/sph/common/mesh.h Normal file
View File

@@ -0,0 +1,160 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_MESH
#define DEF_MESH
#include <vector>
#include <gl/glut.h>
#include "geomx.h"
#include "mesh_info.h"
#include "vector.h"
//#include "mfile.h"
//#define MESH_DEBUG
#ifdef MESH_DEBUG
#define VERT_DELTA 10000
#define EDGE_DELTA 20000
#define FACE_DELTA 30000
#else
#define VERT_DELTA 0
#define EDGE_DELTA 0
#define FACE_DELTA 0
#endif
#define PLY_UINT 0
#define PLY_INT 1
#define PLY_FLOAT 2
#define PLY_LIST 3
#define PLY_VERTS 4
#define PLY_FACES 5
struct PlyProperty {
char type;
std::string name;
};
struct PlyElement {
int num;
char type; // 0 = vert, 1 = face
std::vector<PlyProperty> prop_list;
};
class Mesh : public GeomX, public MeshInfo {
public:
Mesh ();
//virtual objType GetType () { return 'mesh'; }
// Distributed functions
//virtual void onUpdate ( objData dat, mint::Event* e );
//void UpdateMesh ();
// Generic functions
void InitStatic ();
void DrawGL ( float* viewmat );
void DrawFaceGL ( float* viewmat );
void Measure ();
Mesh& operator= ( Mesh& op2 );
// Load PLY mesh
void LoadPly ( char* fname, float s );
void AddPlyElement ( char typ, int n );
void AddPlyProperty ( char typ, std::string name );
void LoadPlyVerts ();
void LoadPlyFaces ();
int FindPlyElem ( char typ );
int FindPlyProp ( int elem, std::string name );
// Vertex, Face, Edge functions
xref AddVert (float x, float y, float z ) { return (this->*m_AddVertFunc) (x, y, z); }
xref AddFaceFast (xref v1, xref v2, xref v3 ) { return (this->*m_AddFaceFast3Func) (v1, v2, v3); }
xref AddFaceFast (xref v1, xref v2, xref v3, xref v4 ) { return (this->*m_AddFaceFast4Func) (v1, v2, v3, v4); }
xref (Mesh::*m_AddVertFunc) (float x, float y, float z);
xref (Mesh::*m_AddFaceFast3Func) (xref v1, xref v2, xref v3);
xref (Mesh::*m_AddFaceFast4Func) (xref v1, xref v2, xref v3, xref v4);
int NumVert () { return NumElem ( m_Vbuf ); }
int NumEdge () { return NumElem ( m_Ebuf ); }
int NumFace () { return NumElem ( m_Fbuf ); }
void IncFace ( int n ) { m_CurrF += n; }
void DebugHeap ();
// FVF - Face-Vertex-Face Mesh
void CreateFVF ();
void ClearFVF ();
void SetFuncFVF ();
xref AddVertFVF ( float x, float y, float z );
xref AddFaceFast3FVF ( xref v1, xref v2, xref v3 );
xref AddFaceFast4FVF ( xref v1, xref v2, xref v3, xref v4 );
VertFVF* GetVertFVF ( int n ) { return (VertFVF*) (mBuf[m_Vbuf].data + n*mBuf[m_Vbuf].stride); }
FaceFVF* GetFaceFVF ( int n ) { return (FaceFVF*) (mBuf[m_Fbuf].data + n*mBuf[m_Fbuf].stride); }
void* GetExtraFVF ( VertFVF* v ) { return ((char*) v + miBufSize[(int) FVF][BVert]); }
void ComputeNormalsFVF ();
void SetNormalFVF ( int n, Vector3DF norm );
void SetColorFVF ( int n, DWORD clr );
void SmoothFVF ( int iter );
void DebugFVF ();
void DrawVertsFVF ( float* viewmat, int a, int b );
void DrawFacesFVF ( float* viewmat, int a, int b );
// CM - Connected Mesh
void CreateCM ();
void SetFuncCM ();
xref AddVertCM ( float x, float y, float z );
xref AddFaceFast3CM ( xref v1, xref v2, xref v3 );
xref AddFaceFast4CM ( xref v1, xref v2, xref v3, xref v4 );
xref AddEdgeCM ( xref v1, xref v2 );
xref FindEdgeCM ( xref v1, xref v2 );
VertCM* GetVertCM ( int n ) { return (VertCM*) (mBuf[m_Vbuf].data + n*mBuf[m_Vbuf].stride); }
EdgeCM* GetEdgeCM ( int n ) { return (EdgeCM*) (mBuf[m_Ebuf].data + n*mBuf[m_Ebuf].stride); }
FaceCM* GetFaceCM ( int n ) { return (FaceCM*) (mBuf[m_Fbuf].data + n*mBuf[m_Fbuf].stride); }
void* GetExtraCM ( VertCM* v ) { return ((char*) v + miBufSize[(int) CM][BVert] ); }
void DebugCM ();
void DrawVertsCM ( float* viewmat, int a, int b );
void DrawFacesCM ( float* viewmat, int a, int b );
void DrawEdgesCM ( float* viewmat, int a, int b );
MFormat GetMeshBufs ( char& v, char& e, char& f ) { v = m_Vbuf; e = m_Ebuf; f = m_Fbuf; return m_Mform; }
protected:
MFormat m_Mform; // Mesh format
char m_Vbuf;
char m_Ebuf;
char m_Fbuf;
int m_CurrF;
std::vector< PlyElement* > m_Ply;
//File m_File;
int m_PlyCurrElem;
static bool mbInitStatic;
Vector3DF mT;
};
#endif

View File

@@ -0,0 +1,97 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_MESH_INFO
#define DEF_MESH_INFO
#include "common_defs.h"
//#include "mint_config.h"
typedef signed int xref;
#define MAX_MFORMAT 10
#define MAX_BFORMAT 5
// CM - Connected mesh
struct FaceCM {
xref e1, e2, e3, e4;
xref v1, v2, v3, v4;
};
struct EdgeCM {
xref v1, v2;
xref f1, f2;
};
struct VertCM {
hList elist;
hList flist;
float x, y, z;
};
// FVF - Face-vertex-face mesh
struct FaceFVF {
xref v1, v2, v3, v4;
};
struct VertFVF {
hList flist;
float x, y, z;
};
// Extra attributes
struct AttrPos {
float x, y, z;
};
struct AttrClr {
DWORD clr;
};
struct AttrNorm {
float nx, ny, nz;
};
struct AttrTex {
float tu, tv;
};
class MeshInfo {
public:
enum MFormat { // Mesh format
UDef = 0,
VV = 1, // Vertex-Vertex
FV = 2, // Face-Vertex
FVF = 3,
WE = 4, // Winged-Edge
CM = 5 // Connected-Mesh
};
enum BFormat { // Buffer format
BVert = 0,
BEdge = 1,
BFace = 2,
};
enum AFormat { // Extra Attribute formats
APos = 0,
AClr = 1,
ANorm = 2,
ATex = 3
};
static int BufSize ( MFormat m, BFormat b ) { return miBufSize[(int) m][(int) b]; }
static int miBufSize [MAX_MFORMAT][MAX_BFORMAT];
};
#endif

612
Extras/sph/common/mtime.cpp Normal file
View File

@@ -0,0 +1,612 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifdef _MSC_VER
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include <stdio.h>
#include <time.h>
#include <math.h>
#include "mtime.h"
#include "mdebug.h"
#ifdef _MSC_VER
#define VS2005
#pragma comment ( lib, "winmm.lib" )
LARGE_INTEGER m_BaseCount;
LARGE_INTEGER m_BaseFreq;
#endif
using namespace mint;
const int Time::m_DaysInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
bool Time::m_Started = false;
sjtime m_BaseTime;
sjtime m_BaseTicks;
void mint::start_timing ( sjtime base )
{
m_BaseTime = base;
#ifdef _MSC_VER
m_BaseTicks = timeGetTime();
QueryPerformanceCounter ( &m_BaseCount );
QueryPerformanceFrequency ( &m_BaseFreq );
#else
struct timeval tv;
gettimeofday(&tv, NULL);
m_BaseTicks = ((sjtime) tv.tv_sec * 1000000LL) + (sjtime) tv.tv_usec;
#endif
}
void Time::SetSystemTime ( int accuracy )
{
switch ( accuracy ) {
case ACC_SEC: // 1 second accuracy
SetSystemTime ();
break;
case ACC_MSEC: { // 1 millisecond accuracy
#ifdef _MSC_VER
m_CurrTime = m_BaseTime + sjtime(timeGetTime() - m_BaseTicks)*MSEC_SCALAR;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
sjtime t = ((sjtime) tv.tv_sec * 1000000LL) + (sjtime) tv.tv_usec;
m_CurrTime = m_BaseTime + ( t - m_BaseTicks) * 1000LL; // 1000LL - converts microseconds to milliseconds
#endif
} break;
case ACC_NSEC: { // 1 nanosecond accuracy
#ifdef _MSC_VER
LARGE_INTEGER currCount;
QueryPerformanceCounter ( &currCount );
m_CurrTime = m_BaseTime + sjtime( (double(currCount.QuadPart-m_BaseCount.QuadPart) / m_BaseFreq.QuadPart) * SEC_SCALAR);
#else
debug.Printf ( "mtime", "ERROR: ACC_NSEC NOT IMPLEMENTED for Time::SetSystemTime\n" );
#endif
} break;
}
}
Time::Time ()
{
if ( !m_Started ) {
m_Started = true;
SetSystemTime (); // Get base time from wall clock
start_timing ( m_CurrTime ); // Start timing from base time
}
m_CurrTime = 0;
}
// Note regarding hours:
// 0 <= hr <= 23
// hr = 0 is midnight (12 am)
// hr = 1 is 1 am
// hr = 12 is noon
// hr = 13 is 1 pm (subtract 12)
// hr = 23 is 11 pm (subtact 12)
// GetScaledJulianTime
// Returns -1.0 if the time specified is invalid.
sjtime Time::GetScaledJulianTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns )
{
double MJD; // Modified Julian Date (JD - 2400000.5)
sjtime SJT; // Scaled Julian Time SJT = MJD * 86400000 + UT
// Check if date/time is valid
if (m <=0 || m > 12) return (sjtime) -1;
if ( y % 4 == 0 && m == 2) { // leap year in february
if (d <=0 || d > m_DaysInMonth[m]+1) return (sjtime) -1;
} else {
if (d <=0 || d > m_DaysInMonth[m]) return (sjtime) -1;
}
if (hr < 0 || hr > 23) return (sjtime) -1;
if (min < 0 || min > 59) return (sjtime) -1;
// Compute Modified Julian Date
MJD = 367 * y - int ( 7 * (y + int (( m + 9)/12)) / 4 );
MJD -= int ( 3 * (int((y + (m - 9)/7)/100) + 1) / 4);
MJD += int ( 275 * m / 9 ) + d + 1721028.5 - 1.0;
MJD -= 2400000.5;
// Compute Scaled Julian Time
SJT = sjtime(MJD) * sjtime( DAY_SCALAR );
SJT += hr * HR_SCALAR + min * MIN_SCALAR + s * SEC_SCALAR + ms * MSEC_SCALAR + ns * NSEC_SCALAR;
return SJT;
}
sjtime Time::GetScaledJulianTime ( int hr, int min, int m, int d, int y )
{
return GetScaledJulianTime ( hr, min, m, d, y, 0, 0, 0 );
}
void Time::GetTime ( sjtime SJT, int& hr, int& min, int& m, int& d, int& y)
{
int s = 0, ms = 0, ns = 0;
GetTime ( SJT, hr, min, m, d, y, s, ms, ns );
}
void Time::GetTime ( sjtime SJT, int& hr, int& min, int& m, int& d, int& y, int& s, int &ms, int& ns)
{
// Compute Universal Time from SJT
sjtime UT = sjtime( SJT % sjtime( DAY_SCALAR ) );
// Compute Modified Julian Date from SJT
double MJD = double(SJT / DAY_SCALAR);
// Use MJD to get Month, Day, Year
double z = floor ( MJD + 1 + 2400000.5 - 1721118.5);
double g = z - 0.25;
double a = floor ( g / 36524.25 );
double b = a - floor ( a / 4.0 );
y = int( floor (( b + g ) / 365.25 ) );
double c = b + z - floor ( 365.25 * y );
m = int (( 5 * c + 456) / 153 );
d = int( c - int (( 153 * m - 457) / 5) );
if (m > 12) {
y++;
m -= 12;
}
// Use UT to get Hrs, Mins, Secs, Msecs
hr = int( UT / HR_SCALAR );
UT -= hr * HR_SCALAR;
min = int( UT / MIN_SCALAR );
UT -= min * MIN_SCALAR;
s = int ( UT / SEC_SCALAR );
UT -= s * SEC_SCALAR;
ms = int ( UT / MSEC_SCALAR );
UT -= ms * MSEC_SCALAR;
ns = int ( UT / NSEC_SCALAR );
// UT Example:
// MSEC_SCALAR = 1
// SEC_SCALAR = 1,000
// MIN_SCALAR = 60,000
// HR_SCALAR = 3,600,000
// DAY_SCALAR = 86,400,000
//
// 7:14:03, 32 msec
// UT = 7*3,600,000 + 14*60,000 + 3*1,000 + 32 = 26,043,032
//
// 26,043,032 / 3,600,000 = 7 26,043,032 - (7 * 3,600,000) = 843,032
// 843,032 / 60,000 = 14 843,032 - (14 * 60,000) = 3,032
// 3,032 / 1,000 = 3 3,032 - (3 * 1,000) = 32
// 32 / 1 = 32
}
void Time::GetTime (int& s, int& ms, int& ns )
{
int hr, min, m, d, y;
GetTime ( m_CurrTime, hr, min, m, d, y, s, ms, ns );
}
void Time::GetTime (int& hr, int& min, int& m, int& d, int& y)
{
GetTime ( m_CurrTime, hr, min, m, d, y);
}
void Time::GetTime (int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns)
{
GetTime ( m_CurrTime, hr, min, m, d, y, s, ms, ns);
}
bool Time::SetTime ( int sec )
{
int hr, min, m, d, y;
GetTime ( m_CurrTime, hr, min, m, d, y );
m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, sec, 0, 0 );
return true;
}
bool Time::SetTime ( int sec, int msec )
{
int hr, min, m, d, y;
GetTime ( m_CurrTime, hr, min, m, d, y );
m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, sec, msec, 0 );
return true;
}
bool Time::SetTime (int hr, int min, int m, int d, int y)
{
int s, ms, ns;
GetTime ( s, ms, ns );
m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, s, ms, ns );
if (m_CurrTime == -1.0) return false;
return true;
}
bool Time::SetTime (int hr, int min, int m, int d, int y, int s, int ms, int ns)
{
m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, s, ms, ns );
if (m_CurrTime == -1.0) return false;
return true;
}
bool Time::SetTime ( std::string line )
{
int hr, min, m, d, y;
std::string dat;
if ( line.substr ( 0, 1 ) == " " )
dat = line.substr ( 1, line.length()-1 ).c_str();
else
dat = line;
hr = atoi ( dat.substr ( 0, 2).c_str() );
min = atoi ( dat.substr ( 3, 2).c_str() );
m = atoi ( dat.substr ( 6, 2).c_str () );
d = atoi ( dat.substr ( 9, 2).c_str () );
y = atoi ( dat.substr ( 12, 4).c_str () );
return SetTime ( hr, min, m, d, y);
}
bool Time::SetDate ( std::string line )
{
int hr, min, m, d, y;
std::string dat;
if ( line.substr ( 0, 1 ) == " " )
dat = line.substr ( 1, line.length()-1 ).c_str();
else
dat = line;
hr = 0;
min = 0;
m = atoi ( dat.substr ( 0, 2).c_str () );
d = atoi ( dat.substr ( 3, 2).c_str () );
y = atoi ( dat.substr ( 6, 4).c_str () );
return SetTime ( hr, min, m, d, y);
}
std::string Time::GetDayOfWeekName ()
{
switch (GetDayOfWeek()) {
case 1: return "Sunday"; break;
case 2: return "Monday"; break;
case 3: return "Tuesday"; break;
case 4: return "Wednesday"; break;
case 5: return "Thursday"; break;
case 6: return "Friday"; break;
case 7: return "Saturday"; break;
}
return "day error";
}
int Time::GetDayOfWeek ()
{
// Compute Modified Julian Date
double MJD = (double) m_CurrTime / sjtime( DAY_SCALAR );
// Compute Julian Date
double JD = floor ( MJD + 1 + 2400000.5 );
int dow = (int(JD - 0.5) % 7) + 4;
if (dow > 7) dow -= 7;
// day of week (1 = sunday, 7 = saturday)
return dow ;
}
int Time::GetWeekOfYear ()
{
int hr, min, m, d, y;
GetTime ( hr, min, m, d, y );
double mjd_start = (double) GetScaledJulianTime ( 0, 0, 1, 1, y ) / DAY_SCALAR; // mjt for jan 1st of year
double mjd_curr = (double) GetScaledJulianTime ( 0, 0, m, d, y ) / DAY_SCALAR; // mjt for specified day in year
double JD = floor ( mjd_start + 1 + 2400000.5 );
int dow = (int ( JD - 0.5 ) % 7) + 4; // day of week for jan 1st of year.
if (dow > 7) dow -= 7;
// week of year (first week in january = week 0)
return int((mjd_curr - mjd_start + dow -1 ) / 7 );
}
int Time::GetElapsedDays ( Time& base )
{
return int( sjtime(m_CurrTime - base.GetSJT() ) / sjtime( DAY_SCALAR ) );
}
int Time::GetElapsedWeeks ( Time& base )
{
return GetElapsedDays(base) / 7;
}
int Time::GetElapsedMonths ( Time& base)
{
return int ( double(GetElapsedDays(base)) / 30.416 );
}
int Time::GetElapsedYears ( Time& base )
{
// It is much easier to compute this in m/d/y format rather
// than using julian dates.
int bhr, bmin, bm, bd, by;
int ehr, emin, em, ed, ey;
GetTime ( base.GetSJT(), bhr, bmin, bm, bd, by );
GetTime ( m_CurrTime, ehr, emin, em, ed, ey );
if ( em < bm) {
// earlier month
return ey - by - 1;
} else if ( em > bm) {
// later month
return ey - by;
} else {
// same month
if ( ed < bd ) {
// earlier day
return ey - by - 1;
} else if ( ed >= bd ) {
// later or same day
return ey - by;
}
}
return -1;
}
int Time::GetFracDay ( Time& base )
{
// Resolution = 5-mins
return int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (MIN_SCALAR*5);
}
int Time::GetFracWeek ( Time& base )
{
// Resolution = 1 hr
int day = GetElapsedDays(base) % 7; // day in week
int hrs = int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (HR_SCALAR);
return day * 24 + hrs;
}
int Time::GetFracMonth ( Time& base )
{
// Resolution = 4 hrs
int day = (int) fmod ( double(GetElapsedDays(base)), 30.416 ); // day in month
int hrs = int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (HR_SCALAR*4);
return day * (24 / 4) + hrs;
}
int Time::GetFracYear ( Time& base )
{
// It is much easier to compute this in m/d/y format rather
// than using julian dates.
int bhr, bmin, bm, bd, by;
int ehr, emin, em, ed, ey;
sjtime LastFullYear;
GetTime ( base.GetSJT() , bhr, bmin, bm, bd, by );
GetTime ( m_CurrTime, ehr, emin, em, ed, ey );
if ( em < bm) {
// earlier month
LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey - 1);
return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) );
} else if ( em > bm) {
// later month
LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey);
return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) );
} else {
// same month
if ( ed < bd ) {
// earlier day
LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey - 1);
return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) );
} else if ( ed > bd ) {
// later day
LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey);
return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) );
} else {
return 0; // same day
}
}
}
std::string Time::GetReadableDate ()
{
char buf[200];
std::string line;
int hr, min, m, d, y;
GetTime ( hr, min, m, d, y );
sprintf ( buf, "%02d:%02d %02d-%02d-%04d", hr, min, m, d, y);
return std::string ( buf );
}
std::string Time::GetReadableTime ()
{
char buf[200];
std::string line;
int hr, min, m, d, y, s, ms, ns;
GetTime ( hr, min, m, d, y, s, ms, ns );
sprintf ( buf, "%02d:%02d:%02d %03d.%06d %02d-%02d-%04d", hr, min, s, ms, ns, m, d, y);
return std::string ( buf );
}
std::string Time::GetReadableSJT ()
{
char buf[200];
sprintf ( buf, "%I64d", m_CurrTime );
return std::string ( buf );
}
std::string Time::GetReadableTime ( int fmt )
{
char buf[200];
int hr, min, m, d, y, s, ms, ns;
GetTime ( hr, min, m, d, y, s, ms, ns );
switch (fmt) {
case 0: sprintf ( buf, "%02d %03d.%06d", s, ms, ns);
}
return std::string ( buf );
}
void Time::SetSystemTime ()
{
int hr, mn, sec, m, d, y;
char timebuf[100];
char datebuf[100];
std::string line;
#ifdef _MSC_VER
#ifdef VS2005
_strtime_s ( timebuf, 100 );
_strdate_s ( datebuf, 100 );
#else
_strtime ( timebuf );
_strdate ( datebuf );
#endif
#endif
#if (defined(__linux__) || defined(__CYGWIN__))
time_t tt;
struct tm tim;
tt = time(NULL);
localtime_r(&tt, &tim);
sprintf( timebuf, "%02i:%02i:%02i", tim.tm_hour, tim.tm_min, tim.tm_sec);
sprintf( datebuf, "%02i:%02i:%02i", tim.tm_mon, tim.tm_mday, tim.tm_year % 100);
#endif
line = timebuf;
hr = atoi ( line.substr ( 0, 2).c_str() );
mn = atoi ( line.substr ( 3, 2).c_str() );
sec = atoi ( line.substr ( 6, 2).c_str() );
line = datebuf;
m = atoi ( line.substr ( 0, 2).c_str() );
d = atoi ( line.substr ( 3, 2).c_str() );
y = atoi ( line.substr ( 6, 2).c_str() );
// NOTE: This only works from 1930 to 2030
if ( y > 30) y += 1900;
else y += 2000;
SetTime ( hr, mn, m, d, y, sec, 0, 0);
}
double Time::GetSec ()
{
return ((double) m_CurrTime / (double) SEC_SCALAR );
}
int Time::GetMSec ()
{
return ((double) m_CurrTime / (double) MSEC_SCALAR );
/*int s, ms, ns;
GetTime ( s, ms, ns );
return ms;*/
}
void Time::Advance ( Time& t )
{
m_CurrTime += t.GetSJT ();
}
void Time::AdvanceMinutes ( int n)
{
m_CurrTime += (sjtime) MIN_SCALAR * n;
}
void Time::AdvanceHours ( int n )
{
m_CurrTime += (sjtime) HR_SCALAR * n;
}
void Time::AdvanceDays ( int n )
{
m_CurrTime += (sjtime) DAY_SCALAR * n;
}
void Time::AdvanceSec ( int n )
{
m_CurrTime += (sjtime) SEC_SCALAR * n;
}
void Time::AdvanceMins ( int n)
{
m_CurrTime += (sjtime) MIN_SCALAR * n;
}
void Time::AdvanceMSec ( int n )
{
m_CurrTime += (sjtime) MSEC_SCALAR * n;
}
Time& Time::operator= ( const Time& op ) { m_CurrTime = op.m_CurrTime; return *this; }
Time& Time::operator= ( Time& op ) { m_CurrTime = op.m_CurrTime; return *this; }
bool Time::operator< ( const Time& op ) { return (m_CurrTime < op.m_CurrTime); }
bool Time::operator> ( const Time& op ) { return (m_CurrTime > op.m_CurrTime); }
bool Time::operator< ( Time& op ) { return (m_CurrTime < op.m_CurrTime); }
bool Time::operator> ( Time& op ) { return (m_CurrTime > op.m_CurrTime); }
bool Time::operator<= ( const Time& op ) { return (m_CurrTime <= op.m_CurrTime); }
bool Time::operator>= ( const Time& op ) { return (m_CurrTime >= op.m_CurrTime); }
bool Time::operator<= ( Time& op ) { return (m_CurrTime <= op.m_CurrTime); }
bool Time::operator>= ( Time& op ) { return (m_CurrTime >= op.m_CurrTime); }
Time Time::operator- ( Time& op )
{
return Time( m_CurrTime - op.GetSJT() );
}
Time Time::operator+ ( Time& op )
{
return Time( m_CurrTime + op.GetSJT() );
}
bool Time::operator== ( const Time& op )
{
return (m_CurrTime == op.m_CurrTime);
}
bool Time::operator!= ( Time& op )
{
return (m_CurrTime != op.m_CurrTime);
}
void Time::RegressionTest ()
{
// This code verifies the Julian Date calculations are correct for all
// minutes over a range of years. Useful to debug type issues when
// compiling on different platforms.
//
int m, d, y, hr, min;
int cm, cd, cy, chr, cmin;
for (y=2000; y < 2080; y++) {
for (m=1; m <= 12; m++) {
for (d=1; d <= 31; d++) {
for (hr=0; hr<=23; hr++) {
for (min=0; min<=59; min++) {
if ( SetTime ( hr, min, m, d, y, 0, 0, 0 ) ) {
GetTime ( chr, cmin, cm, cd, cy );
if ( hr!=chr || min!=cmin || m!=cm || d!=cd || y!=cy) {
// debug.Printf (" time", "Error: %d, %d, %d, %d, %d = %I64d\n", hr, min, m, d, y, GetSJT());
// debug.Printf (" time", "-----: %d, %d, %d, %d, %d\n", chr, cmin, cm, cd, cy);
}
}
}
}
}
}
// debug.Printf (" time", "Verified: %d\n", y);
}
}

234
Extras/sph/common/mtime.h Normal file
View File

@@ -0,0 +1,234 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TIME_HPP
#define TIME_HPP
#include <string>
#ifdef _MSC_VER
#include <windows.h>
typedef __int64 mstime; // microsecond time = 8 byte integer
typedef __int64 sjtime; // scaled julian times = 8 byte integer
#define MSEC_SCALAR 1000000i64
#define SEC_SCALAR 1000000000i64
#define MIN_SCALAR 60000000000i64
#define HR_SCALAR 3600000000000i64
#define DAY_SCALAR 86400000000000i64
#pragma warning ( disable : 4522 )
#pragma warning ( disable : 4996 ) // sprintf warning
#endif
#ifdef __linux__
#include <linux/types.h>
typedef __s64 mstime;
typedef __s64 sjtime;
#define MSEC_SCALAR 1000000LL
#define SEC_SCALAR 1000000000LL
#define MIN_SCALAR 60000000000LL
#define HR_SCALAR 3600000000000LL
#define DAY_SCALAR 86400000000000LL
#endif
#ifdef __CYGWIN__
#include <largeint.h> // found in \cygwin\usr\include\w32api
typedef __int64 mstime;
typedef __int64 sjtime;
#define MSEC_SCALAR 1000000LL
#define SEC_SCALAR 1000000000LL
#define MIN_SCALAR 60000000000LL
#define HR_SCALAR 3600000000000LL
#define DAY_SCALAR 86400000000000LL
#endif
#define ACC_SEC 0
#define ACC_MSEC 1
#define ACC_NSEC 2
#define NSEC_SCALAR 1
// Time Class
// R. Hoetzlein
//
// Overview:
// There is a need in many systems to represent both very small (nanoseconds) and
// very large (millenia) timescales accurately. Modified Julian Date accurate represents
// individual days over +/- about 30,000 yrs. However, MJD represents fractions of a day
// as a floating point fraction. This is inaccurate for any timing-critical applications.
// The Time class here uses an 8-byte (64 bit) integer called SJT, Scaled Julian Time.
// SJT = MJD * DAY_SCALAR + UT (nanoseconds).
// SJT is the Modified Julian Date scaled by a integer factor, and added to Universal Time
// represented in nanoseconds.
//
// Features:
// - Accurately represents individual nanoseconds over +/- 30,000 yrs.
// - Correct rollover of tiny time scales on month, day, year boundaries.
// e.g. Set date/time to 11:59:59.9999, on Feb 28th,
// - Accurately gives day of the week for any date
// - Accurately compares two dates (days elapsed) even across leap-years.
// - Adjust sec/nsec independently from month/day/year (work at scale you desire)
//
// Implementation Notes:
// JD = Julian Day is the number of days elapsed since Jan 1, 4713 BC in the proleptic Julian calendar.
// http://en.wikipedia.org/wiki/Julian_day
// MJD = Modified Julian Date. Most modern dates, after 19th c., have Julian Date which are greater
// than 2400000.5. MJD is an offset. MJD = JD - 2400000.5
// It shifts the epoch date (start date) to Nov 17, 1858.
// UT = Universal Time. This is the time of day in hours as measured from Greenwich England.
// For non-astronomic uses, this is: UT = Local Time + Time Zone.
// SJT = Scaled Julian Time = MJD * DAY_SCALAR + UT (in nanoseconds).
//
// Julian Dates (and their MJD and SJT equivalents)
// ------------
// Jan 1, 4713 BC = JD 0 = MJD -2400000 = SJT
// Jan 1, 1500 AD = JD 2268933.5 = MJD -131067 = SJT
// Nov 16, 1858 AD = JD 2400000.5 = MJD 0 = SJT 0
// Jan 1, 1960 AD = JD 2436935.5 = MJD 36935 = SJT 3,191,184,000,000
// Jan 1, 2005 AD = JD 2453372.5 = MJD 53372 = SJT 4,611,340,800,000
// Jan 1, 2100 AD = JD 2488070.5 = MJD 88070 = SJT 7,609,248,000,000
//
//
//
// 32/64-Bit Integer Ranges
// 32-bit Integer Min: <20>2,147,483,648 ( 4 bytes )
// 32-bit Integer Max: 2,147,483,647
// SJT 2005: 4,611,340,800,000
// 64-bit Integer Min: <20>9,223,372,036,854,775,808
// 64-bit Integer Max: 9,223,372,036,854,775,807 ( 8 bytes )
//
// SJT Range
// ---------
// * USING DAY_SCALAR = 86,400,000 (millisec accuracy)
// SJT Range = (+/-9,223,372,036,854,775,807 SJT / 86,400,000 DAY_SCALAR)
// SJT Range (in Julian Days) = +2400000.5 + (+/-106,751,991,167 MJD)
// SJT Range (in Julian Days) = +/- 292278883 years, with 1 millisecond accuracy.
//
// * USING DAY_SCALAR = 86,400,000,000,000 (nanosec accuracy)
// SJT Range = (+/-9,223,372,036,854,775,807 SJT / 86,400,000,000,000 DAY_SCALAR)
// SJT Range (in Julian Days) = +2400000.5 + (+/-106,751 MJD)
// SJT Range (in Julian Days) = 1566 AD to 2151 AD, with 1 nanosecond accuracy.
namespace mint {
class Time {
public:
Time ();
Time ( sjtime t ) { m_CurrTime = t; }
Time ( int sec, int msec ) { m_CurrTime = 0; SetTime ( sec, msec ); }
// Set time
bool SetTime ( int sec ); // Set seconds
bool SetTime ( int sec, int msec ); // Set seconds, msecs
bool SetTime ( int hr, int min, int m, int d, int y); // Set hr/min, month, day, year
bool SetTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns); // Set hr/min, month, day, year, sec, ms, ns
bool SetTime ( Time& t ) { m_CurrTime = t.GetSJT(); return true;} // Set to another Time object
bool SetTime ( std::string line ); // Set time from string (hr,min,sec)
bool SetDate ( std::string line ); // Set date from string (mo,day,yr)
void SetSystemTime (); // Set date/time to system clock
void SetSystemTime ( int accuracy ); // Set date/time to system clock
void SetSJT ( sjtime t ) { m_CurrTime = t ;} // Set Scaled Julian Time directly
// Get time
void GetTime (int& sec, int& msec, int& nsec );
void GetTime (int& hr, int& min, int& m, int& d, int& y);
void GetTime (int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns);
double GetSec ();
int GetMSec ();
std::string GetReadableDate ();
std::string GetReadableTime ();
std::string GetReadableTime ( int fmt );
std::string GetReadableSJT ();
std::string GetDayOfWeekName ();
sjtime GetSJT () { return m_CurrTime; }
// Advance Time
void Advance ( Time& t );
void AdvanceMinutes ( int n);
void AdvanceHours ( int n );
void AdvanceDays ( int n );
void AdvanceSec ( int n );
void AdvanceMins ( int n);
void AdvanceMSec ( int n );
// Utility functions
// (these do the actual work, but should not be private as they may be useful to user)
sjtime GetScaledJulianTime ( int hr, int min, int m, int d, int y );
sjtime GetScaledJulianTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns );
void GetTime ( sjtime t, int& hr, int& min, int& m, int& d, int& y);
void GetTime ( sjtime t, int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns);
// Get/Set Julian Date and Modified Julain Date
void SetJD ( double jd );
void SetMJD ( int jd );
double GetJD ();
int GetMJD ();
// Time operators
Time& operator= ( const Time& op );
Time& operator= ( Time& op );
bool operator< ( const Time& op );
bool operator< ( Time& op );
bool operator> ( const Time& op );
bool operator> ( Time& op );
bool operator<= ( const Time& op );
bool operator<= ( Time& op );
bool operator>= ( const Time& op );
bool operator>= ( Time& op );
bool operator== ( const Time& op );
bool operator!= ( Time& op );
Time operator- ( Time& op );
Time operator+ ( Time& op );
// Elapsed Times
int GetElapsedDays ( Time& base );
int GetElapsedWeeks ( Time& base );
int GetElapsedMonths ( Time& base );
int GetElapsedYears ( Time& base );
int GetFracDay ( Time& base ); // Return Unit = 5 mins
int GetFracWeek ( Time& base ); // Return Unit = 1 hr
int GetFracMonth ( Time& base ); // Return Unit = 4 hrs
int GetFracYear ( Time& base ); // Return Unit = 1 day
int GetDayOfWeek ();
int GetWeekOfYear ();
void RegressionTest ();
private:
static const int m_DaysInMonth[13];
static bool m_Started;
sjtime m_CurrTime;
};
// Used for precise system time (Win32)
void start_timing ( sjtime base );
}
#endif

View File

@@ -0,0 +1,23 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "particle.h"

View File

@@ -0,0 +1,29 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_PARTICLE
#define DEF_PARTICLE
#include "vector.h"
#endif

View File

@@ -0,0 +1,539 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "gl_helper.h"
#include "point_set.h"
int PointSet::m_pcurr = -1;
PointSet::PointSet ()
{
m_GridRes.Set ( 0, 0, 0 );
m_pcurr = -1;
Reset ();
}
int PointSet::GetGridCell ( int x, int y, int z )
{
return (int) ( (z*m_GridRes.y + y)*m_GridRes.x + x);
}
Point* PointSet::firstGridParticle ( int gc, int& p )
{
m_pcurr = m_Grid [ gc ];
if ( m_pcurr == -1 ) return 0x0;
p = m_pcurr;
return (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride);
}
Point* PointSet::nextGridParticle ( int& p )
{
Point* pnt = 0x0;
if ( m_pcurr != -1 ) {
pnt = (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride);
p = m_pcurr;
m_pcurr = pnt->next;
}
return pnt;
}
unsigned short* PointSet::getNeighborTable ( int n, int& cnt )
{
cnt = m_NC[n];
if ( cnt == 0 ) return 0x0;
return &m_Neighbor[n][0];
}
float PointSet::GetValue ( float x, float y, float z )
{
float dx, dy, dz, dsq;
float sum;
int pndx;
Point* pcurr;
float R2 = 1.8*1.8;
Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 );
int cnt = 0;
sum = 0.0;
for (int cell=0; cell < 8; cell++ ) {
if ( m_GridCell[cell] != -1 ) {
pndx = m_Grid [ m_GridCell[cell] ];
while ( pndx != -1 ) {
pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride);
dx = x - pcurr->pos.x;
dy = y - pcurr->pos.y;
dz = z - pcurr->pos.z;
dsq = dx*dx+dy*dy+dz*dz;
if ( dsq < R2 ) sum += R2 / dsq;
pndx = pcurr->next;
}
}
}
return sum;
}
Vector3DF PointSet::GetGradient ( float x, float y, float z )
{
Vector3DF norm;
float dx, dy, dz, dsq;
float sum;
int pndx;
Point* pcurr;
float R2 = (m_GridCellsize/2.0)*(m_GridCellsize/2.0);
Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 );
int cnt = 0;
sum = 0.0;
norm.Set (0,0,0);
for (int cell=0; cell < 8; cell++ ) {
if ( m_GridCell[cell] != -1 ) {
pndx = m_Grid [ m_GridCell[cell] ];
while ( pndx != -1 ) {
pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride);
dx = x - pcurr->pos.x;
dy = y - pcurr->pos.y;
dz = z - pcurr->pos.z;
dsq = dx*dx+dy*dy+dz*dz;
if ( dsq > 0 && dsq < R2 ) {
dsq = 2.0*R2 / (dsq*dsq);
norm.x += dx * dsq;
norm.y += dy * dsq;
norm.z += dz * dsq;
}
pndx = pcurr->next;
}
}
}
norm.Normalize ();
return norm;
}
DWORD PointSet::GetColor ( float x, float y, float z )
{
Vector3DF clr;
float dx, dy, dz, dsq;
float sum;
int pndx;
Point* pcurr;
float R2 = (m_GridCellsize/2.0)*(m_GridCellsize/2.0);
Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 );
int cnt = 0;
sum = 0.0;
clr.Set (0,0,0);
for (int cell=0; cell < 8; cell++ ) {
if ( m_GridCell[cell] != -1 ) {
pndx = m_Grid [ m_GridCell[cell] ];
while ( pndx != -1 ) {
pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride);
dx = x - pcurr->pos.x;
dy = y - pcurr->pos.y;
dz = z - pcurr->pos.z;
dsq = dx*dx+dy*dy+dz*dz;
if ( dsq < R2 ) {
dsq = 2.0*R2 / (dsq*dsq);
clr.x += RED(pcurr->clr) * dsq;
clr.y += GRN(pcurr->clr) * dsq;
clr.z += BLUE(pcurr->clr) * dsq;
}
pndx = pcurr->next;
}
}
}
clr.Normalize ();
return COLORA(clr.x, clr.y, clr.z, 1.0);
}
void PointSet::Reset ()
{
// Reset number of particles
// ResetBuffer ( 0 );
m_Time = 0;
m_DT = 0.1;
m_Param[POINT_GRAV] = 100.0;
m_Param[PLANE_GRAV] = 0.0;
m_Vec[ POINT_GRAV_POS].Set(0,0,50.0);
m_Vec[ PLANE_GRAV_DIR].Set(0,0,-9.8);
m_Vec[ EMIT_RATE ].Set ( 1, 10, 0 );
m_Vec[ EMIT_POS ].Set ( 50, 0, 35 );
m_Vec[ EMIT_ANG ].Set ( 90, 45, 50.0 );
m_Vec[ EMIT_DANG ].Set ( 0, 0, 0 );
m_Vec[ EMIT_SPREAD ].Set ( 4, 4, 1 );
}
void PointSet::Initialize ( int mode, int total )
{
switch (mode) {
case BPOINT: {
FreeBuffers ();
AddBuffer ( BPOINT, sizeof ( Point ), total );
AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "color", sizeof ( DWORD ), false );
Reset ();
} break;
case BPARTICLE: {
FreeBuffers ();
AddBuffer ( BPARTICLE, sizeof ( Particle ), total );
AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "color", sizeof ( DWORD ), false );
AddAttribute ( 0, "vel", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "ndx", sizeof ( unsigned short ), false );
AddAttribute ( 0, "age", sizeof ( unsigned short ), false );
Reset ();
} break;
}
}
int PointSet::AddPoint ()
{
xref ndx;
AddElem ( 0, ndx );
return ndx;
}
int PointSet::AddPointReuse ()
{
xref ndx;
if ( NumPoints() < mBuf[0].max-1 )
AddElem ( 0, ndx );
else
RandomElem ( 0, ndx );
return ndx;
}
void PointSet::AddVolume ( Vector3DF min, Vector3DF max, float spacing )
{
Vector3DF pos;
Point* p;
float dx, dy, dz;
dx = max.x-min.x;
dy = max.y-min.y;
dz = max.z-min.z;
for (float z = max.z; z >= min.z; z -= spacing ) {
for (float y = min.y; y <= max.y; y += spacing ) {
for (float x = min.x; x <= max.x; x += spacing ) {
p = GetPoint ( AddPointReuse () );
pos.Set ( x, y, z);
//pos.x += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
//pos.y += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
//pos.z += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
p->pos = pos;
p->clr = COLORA( (x-min.x)/dx, (y-min.y)/dy, (z-min.z)/dz, 1);
}
}
}
}
void PointSet::Draw ( float* view_mat, float rad )
{
char* dat;
Point* p;
glEnable ( GL_NORMALIZE );
if ( m_Param[PNT_DRAWMODE] == 0 ) {
glLoadMatrixf ( view_mat );
dat = mBuf[0].data;
for (int n = 0; n < NumPoints(); n++) {
p = (Point*) dat;
glPushMatrix ();
glTranslatef ( p->pos.x, p->pos.y, p->pos.z );
glScalef ( 0.2, 0.2, 0.2 );
glColor4f ( RED(p->clr), GRN(p->clr), BLUE(p->clr), ALPH(p->clr) );
drawSphere ();
glPopMatrix ();
dat += mBuf[0].stride;
}
} else if ( m_Param[PNT_DRAWMODE] == 1 ) {
glLoadMatrixf ( view_mat );
dat = mBuf[0].data;
glBegin ( GL_POINTS );
for (int n=0; n < NumPoints(); n++) {
p = (Point*) dat;
glColor3f ( RED(p->clr), GRN(p->clr), BLUE(p->clr) );
glVertex3f ( p->pos.x, p->pos.y, p->pos.z );
dat += mBuf[0].stride;
}
glEnd ();
}
}
void PointSet::Emit ( float spacing )
{
Particle* p;
Vector3DF dir;
Vector3DF pos;
float ang_rand, tilt_rand;
float rnd = m_Vec[EMIT_RATE].y * 0.15;
int x = (int) sqrt(m_Vec[EMIT_RATE].y);
for ( int n = 0; n < m_Vec[EMIT_RATE].y; n++ ) {
ang_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].x;
tilt_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].y;
dir.x = cos ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
dir.y = sin ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
dir.z = cos ( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
pos = m_Vec[EMIT_POS];
pos.x += spacing * (n/x);
pos.y += spacing * (n%x);
p = (Particle*) GetElem( 0, AddPointReuse () );
p->pos = pos;
p->vel = dir;
p->vel_eval = dir;
p->age = 0;
p->clr = COLORA ( m_Time/10.0, m_Time/5.0, m_Time /4.0, 1 );
}
}
void PointSet::Run ()
{
if ( m_Vec[EMIT_RATE].x > 0 && ++m_Frame >= (int) m_Vec[EMIT_RATE].x ) {
m_Frame = 0;
Emit ( 1.0 );
}
Advance();
}
void PointSet::Advance ()
{
char* dat;
Particle* p;
Vector3DF vnext, accel, norm;
vnext = m_Vec[EMIT_DANG];
vnext *= m_DT;
m_Vec[EMIT_ANG] += vnext;
dat = mBuf[0].data;
for ( int c = 0; c < NumPoints(); c++ ) {
p = (Particle*) dat;
accel.Set (0, 0, 0);
// Plane gravity
if ( m_Param[PLANE_GRAV] > 0)
accel += m_Vec[PLANE_GRAV_DIR];
// Point gravity
if ( m_Param[POINT_GRAV] > 0 ) {
norm.x = ( p->pos.x - m_Vec[POINT_GRAV_POS].x );
norm.y = ( p->pos.y - m_Vec[POINT_GRAV_POS].y );
norm.z = ( p->pos.z - m_Vec[POINT_GRAV_POS].z );
norm.Normalize ();
norm *= m_Param[POINT_GRAV];
accel -= norm;
}
// Leapfrog Integration ----------------------------
vnext = accel;
vnext *= m_DT;
vnext += p->vel; // v(t+1/2) = v(t-1/2) + a(t) dt
p->vel_eval = p->vel;
p->vel_eval += vnext;
p->vel_eval *= 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
p->vel = vnext;
vnext *= m_DT;
p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt
// Euler integration -------------------------------
// accel += m_Gravity;
// accel *= m_DT;
// mParticles[c].vel += accel; // v(t+1) = v(t) + a(t) dt
// mParticles[c].vel_eval += accel;
// mParticles[c].vel_eval *= m_DT/d;
// mParticles[c].pos += mParticles[c].vel_eval;
// mParticles[c].vel_eval = mParticles[c].vel;
dat += mBuf[0].stride;
}
m_Time += m_DT;
}
// Ideal grid cell size (gs) = 2 * smoothing radius = 0.02*2 = 0.04
// Ideal domain size = k*gs/d = k*0.02*2/0.005 = k*8 = {8, 16, 24, 32, 40, 48, ..}
// (k = number of cells, gs = cell size, d = simulation scale)
void PointSet::Grid_Setup ( Vector3DF min, Vector3DF max, float sim_scale, float cell_size, float border )
{
float world_cellsize = cell_size / sim_scale;
m_Grid.clear ();
m_GridMin = min; m_GridMin -= border;
m_GridMax = max; m_GridMax += border;
m_GridSize = m_GridMax;
m_GridSize -= m_GridMin;
m_GridCellsize = world_cellsize;
m_GridRes.x = ceil ( m_GridSize.x / world_cellsize ); // Determine grid resolution
m_GridRes.y = ceil ( m_GridSize.y / world_cellsize );
m_GridRes.z = ceil ( m_GridSize.z / world_cellsize );
m_GridSize.x = m_GridRes.x * cell_size / sim_scale; // Adjust grid size to multiple of cell size
m_GridSize.y = m_GridRes.y * cell_size / sim_scale;
m_GridSize.z = m_GridRes.z * cell_size / sim_scale;
m_GridDelta = m_GridRes; // delta = translate from world space to cell #
m_GridDelta /= m_GridSize;
m_GridTotal = (int)(m_GridSize.x * m_GridSize.y * m_GridSize.z);
m_Grid.clear ();
m_GridCnt.clear ();
m_Grid.reserve ( m_GridTotal );
m_GridCnt.reserve ( m_GridTotal );
for (int n=0; n < m_GridTotal; n++) {
m_Grid.push_back ( -1 );
m_GridCnt.push_back ( 0 );
}
}
void PointSet::Grid_Draw ( float* view_mat )
{
float clr;
int cx, cy, cz;
float x1, y1, z1;
float x2, y2, z2;
int g = 0;
glLoadMatrixf ( view_mat );
glColor3f ( 0.7, 0.7, 0.7 );
glBegin ( GL_LINES );
cz = 0;
//for ( cz = 0; cz < m_GridRes.z; cz++ ) {
for ( cy = 0; cy < m_GridRes.y; cy++ ) {
for ( cx = 0; cx < m_GridRes.x; cx++ ) {
// Cell is not empty. Process it.
//if ( m_Grid[g] != 0x0 ) {
// clr = m_GridCnt[g]/30.0;
clr = 0.25;
if ( clr <0.25) clr =0.25;
if ( clr >1) clr =1 ;
glColor3f ( clr, clr, clr );
x1 = (cx * m_GridDelta.x) + m_GridMin.x; x2 = ((cx+1) * m_GridDelta.x) + m_GridMin.x;
y1 = (cy * m_GridDelta.y) + m_GridMin.y; y2 = ((cy+1) * m_GridDelta.y) + m_GridMin.y;
z1 = (cz * m_GridDelta.z) + m_GridMin.z; z2 = ((cz+1) * m_GridDelta.z) + m_GridMin.z;
glVertex3f ( x1, y1, z1 ); glVertex3f ( x2, y1, z1 );
glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y2, z1 );
glVertex3f ( x2, y2, z1 ); glVertex3f ( x1, y2, z1 );
glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y1, z1 );
glVertex3f ( x1, y1, z2 ); glVertex3f ( x2, y1, z2 );
glVertex3f ( x2, y1, z2 ); glVertex3f ( x2, y2, z2 );
glVertex3f ( x2, y2, z2 ); glVertex3f ( x1, y2, z2 );
glVertex3f ( x1, y2, z2 ); glVertex3f ( x1, y1, z2 );
glVertex3f ( x1, y1, z1 ); glVertex3f ( x1, y1, z2 );
glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y2, z2 );
glVertex3f ( x2, y2, z1 ); glVertex3f ( x2, y2, z2 );
glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y1, z2 );
//}
g++;
}
}
//}
glEnd ();
}
void PointSet::Grid_InsertParticles ()
{
char *dat1, *dat1_end;
Point *p;
int gs;
int gx, gy, gz;
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride )
((Point*) dat1)->next = -1;
for (int n=0; n < m_GridTotal; n++) {
m_Grid[n] = -1;
m_GridCnt[n] = 0;
}
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
int n = 0;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
p = (Point*) dat1;
gx = (int)( (p->pos.x - m_GridMin.x) * m_GridDelta.x); // Determine grid cell
gy = (int)( (p->pos.y - m_GridMin.y) * m_GridDelta.y);
gz = (int)( (p->pos.z - m_GridMin.z) * m_GridDelta.z);
gs = (int)( (gz*m_GridRes.y + gy)*m_GridRes.x + gx);
if ( gs >= 0 && gs < m_GridTotal ) {
p->next = m_Grid[gs];
m_Grid[gs] = n;
m_GridCnt[gs]++;
}
n++;
}
}
int PointSet::Grid_FindCell ( Vector3DF p )
{
int gc;
Vector3DI cell;
cell.x = (int) (p.x - m_GridMin.x) * m_GridDelta.x;
cell.y = (int) (p.y - m_GridMin.y) * m_GridDelta.y;
cell.z = (int) (p.z - m_GridMin.z) * m_GridDelta.z;
gc = (int)( (cell.z*m_GridRes.y + cell.y)*m_GridRes.x + cell.x);
if ( gc < 0 || gc > m_GridTotal ) return -1;
return gc;
}
void PointSet::Grid_FindCells ( Vector3DF p, float radius )
{
Vector3DI sph_min;
// Compute sphere range
sph_min.x = (int)((-radius + p.x - m_GridMin.x) * m_GridDelta.x);
sph_min.y = (int)((-radius + p.y - m_GridMin.y) * m_GridDelta.y);
sph_min.z = (int)((-radius + p.z - m_GridMin.z) * m_GridDelta.z);
if ( sph_min.x < 0 ) sph_min.x = 0;
if ( sph_min.y < 0 ) sph_min.y = 0;
if ( sph_min.z < 0 ) sph_min.z = 0;
m_GridCell[0] = (int)((sph_min.z * m_GridRes.y + sph_min.y) * m_GridRes.x + sph_min.x);
m_GridCell[1] = m_GridCell[0] + 1;
m_GridCell[2] = (int)(m_GridCell[0] + m_GridRes.x);
m_GridCell[3] = m_GridCell[2] + 1;
if ( sph_min.z+1 < m_GridRes.z ) {
m_GridCell[4] = (int)(m_GridCell[0] + m_GridRes.y*m_GridRes.x);
m_GridCell[5] = m_GridCell[4] + 1;
m_GridCell[6] = (int)(m_GridCell[4] + m_GridRes.x);
m_GridCell[7] = m_GridCell[6] + 1;
}
if ( sph_min.x+1 >= m_GridRes.x ) {
m_GridCell[1] = -1; m_GridCell[3] = -1;
m_GridCell[5] = -1; m_GridCell[7] = -1;
}
if ( sph_min.y+1 >= m_GridRes.y ) {
m_GridCell[2] = -1; m_GridCell[3] = -1;
m_GridCell[6] = -1; m_GridCell[7] = -1;
}
}

View File

@@ -0,0 +1,165 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_POINT_SET
#define DEF_POINT_SET
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "common_defs.h"
#include "geomx.h"
#include "vector.h"
typedef signed int xref;
#define MAX_NEIGHBOR 80
#define MAX_PARAM 21
// Scalar params
#define PNT_DRAWMODE 0
#define PNT_SPHERE 0
#define PNT_POINT 1
#define PNT_DRAWSIZE 1
#define POINT_GRAV 2
#define PLANE_GRAV 3
// Vector params
#define EMIT_POS 0
#define EMIT_ANG 1
#define EMIT_DANG 2
#define EMIT_SPREAD 3
#define EMIT_RATE 4
#define POINT_GRAV_POS 5
#define PLANE_GRAV_DIR 6
#define BPOINT 0
#define BPARTICLE 1
struct Point {
Vector3DF pos;
DWORD clr;
int next;
};
struct Particle {
Vector3DF pos;
DWORD clr;
int next;
Vector3DF vel;
Vector3DF vel_eval;
unsigned short age;
};
class PointSet : public GeomX {
public:
PointSet ();
// Point Sets
virtual void Initialize ( int mode, int max );
virtual void Draw ( float* view_mat, float rad );
virtual void Reset ();
virtual int AddPoint ();
virtual int AddPointReuse ();
Point* GetPoint ( int n ) { return (Point*) GetElem(0, n); }
int NumPoints () { return NumElem(0); }
// Metablobs
virtual float GetValue ( float x, float y, float z );
virtual Vector3DF GetGradient ( float x, float y, float z );
// virtual float GetValue ( float x, float y, float z, Vector3DF& dir );
virtual DWORD GetColor ( float x, float y, float z );
// Particle system
virtual void Run ();
virtual void Advance ();
virtual void Emit ( float spacing );
// Misc
virtual void AddVolume ( Vector3DF min, Vector3DF max, float spacing );
// Parameters
void SetParam (int p, float v ) { m_Param[p] = v; }
void SetParam (int p, int v ) { m_Param[p] = (float) v; }
float GetParam ( int p ) { return (float) m_Param[p]; }
Vector3DF GetVec ( int p ) { return m_Vec[p]; }
void SetVec ( int p, Vector3DF v ) { m_Vec[p] = v; }
void Toggle ( int p ) { m_Toggle[p] = !m_Toggle[p]; }
bool GetToggle ( int p ) { return m_Toggle[p]; }
float GetDT() { return (float) m_DT; }
// Spatial Subdivision
void Grid_Setup ( Vector3DF min, Vector3DF max, float sim_scale, float cell_size, float border );
void Grid_Create ();
void Grid_InsertParticles ();
void Grid_Draw ( float* view_mat );
void Grid_FindCells ( Vector3DF p, float radius );
int Grid_FindCell ( Vector3DF p );
Vector3DF GetGridRes () { return m_GridRes; }
Vector3DF GetGridMin () { return m_GridMin; }
Vector3DF GetGridMax () { return m_GridMax; }
Vector3DF GetGridDelta () { return m_GridDelta; }
int GetGridCell ( int x, int y, int z );
Point* firstGridParticle ( int gc, int& p );
Point* nextGridParticle ( int& p );
unsigned short* getNeighborTable ( int n, int& cnt );
protected:
int m_Frame;
// Parameters
double m_Param [ MAX_PARAM ]; // see defines above
Vector3DF m_Vec [ MAX_PARAM ];
bool m_Toggle [ MAX_PARAM ];
// Particle System
double m_DT;
double m_Time;
// Spatial Grid
std::vector< int > m_Grid;
std::vector< int > m_GridCnt;
int m_GridTotal; // total # cells
Vector3DF m_GridMin; // volume of grid (may not match domain volume exactly)
Vector3DF m_GridMax;
Vector3DF m_GridRes; // resolution in each axis
Vector3DF m_GridSize; // physical size in each axis
Vector3DF m_GridDelta;
float m_GridCellsize;
int m_GridCell[27];
// Neighbor Table
unsigned short m_NC[65536]; // neighbor table (600k)
unsigned short m_Neighbor[65536][MAX_NEIGHBOR];
float m_NDist[65536][MAX_NEIGHBOR];
static int m_pcurr;
};
#endif

View File

@@ -0,0 +1,782 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// Vector Operations Implemented:
// =, +, -, *, / (on vectors and scalars)
// Cross Cross product vector with op
// Dot Dot product vector with op
// Dist (op) Distance from vector to op
// DistSq Distance^2 from vector to op
// Length () Length of vector
// Normalize () Normalizes vector
//
#include "vector.h"
// Vector2DC Code Definition
#define VTYPE unsigned char
#define VNAME 2DC
// Constructors/Destructors
inline Vector2DC::Vector2DC() {x=0; y=0;}
inline Vector2DC::~Vector2DC() {}
inline Vector2DC::Vector2DC (VTYPE xa, VTYPE ya) {x=xa; y=ya;}
inline Vector2DC::Vector2DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DC &Vector2DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DC::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DC &Vector2DC::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
}
return *this;
}
inline double Vector2DC::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DC::X(void) {return x;}
inline VTYPE &Vector2DC::Y(void) {return y;}
inline VTYPE Vector2DC::Z(void) {return 0;}
inline VTYPE Vector2DC::W(void) {return 0;}
inline const VTYPE &Vector2DC::X(void) const {return x;}
inline const VTYPE &Vector2DC::Y(void) const {return y;}
inline const VTYPE Vector2DC::Z(void) const {return 0;}
inline const VTYPE Vector2DC::W(void) const {return 0;}
inline VTYPE *Vector2DC::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector2DI Code Definition
#define VNAME 2DI
#define VTYPE int
// Constructors/Destructors
inline Vector2DI::Vector2DI() {x=0; y=0;}
inline Vector2DI::~Vector2DI() {}
inline Vector2DI::Vector2DI (VTYPE xa, VTYPE ya) {x=xa; y=ya;}
inline Vector2DI::Vector2DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DI &Vector2DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DI::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DI &Vector2DI::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
}
return *this;
}
inline double Vector2DI::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DI::X(void) {return x;}
inline VTYPE &Vector2DI::Y(void) {return y;}
inline VTYPE Vector2DI::Z(void) {return 0;}
inline VTYPE Vector2DI::W(void) {return 0;}
inline const VTYPE &Vector2DI::X(void) const {return x;}
inline const VTYPE &Vector2DI::Y(void) const {return y;}
inline const VTYPE Vector2DI::Z(void) const {return 0;}
inline const VTYPE Vector2DI::W(void) const {return 0;}
inline VTYPE *Vector2DI::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector2DF Code Definition
#define VNAME 2DF
#define VTYPE double
// Constructors/Destructors
inline Vector2DF::Vector2DF() {x=0; y=0;}
inline Vector2DF::~Vector2DF() {}
inline Vector2DF::Vector2DF (const VTYPE xa, const VTYPE ya) {x=xa; y=ya;}
inline Vector2DF::Vector2DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DF &Vector2DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DF::Dot(const Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dot(const Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dot(const Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::DistSq (const Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DF &Vector2DF::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x /= n;
y /= n;
}
return *this;
}
inline double Vector2DF::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DF::X(void) {return x;}
inline VTYPE &Vector2DF::Y(void) {return y;}
inline VTYPE Vector2DF::Z(void) {return 0;}
inline VTYPE Vector2DF::W(void) {return 0;}
inline const VTYPE &Vector2DF::X(void) const {return x;}
inline const VTYPE &Vector2DF::Y(void) const {return y;}
inline const VTYPE Vector2DF::Z(void) const {return 0;}
inline const VTYPE Vector2DF::W(void) const {return 0;}
inline VTYPE *Vector2DF::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DC Code Definition
#define VNAME 3DC
#define VTYPE unsigned char
// Constructors/Destructors
inline Vector3DC::Vector3DC() {x=0; y=0; z=0;}
inline Vector3DC::~Vector3DC() {}
inline Vector3DC::Vector3DC (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DC::Vector3DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Member Functions
inline Vector3DC &Vector3DC::Set (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DC::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DC &Vector3DC::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
z = (VTYPE) (((double) z*255)/n);
}
return *this;
}
inline double Vector3DC::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DC::X(void) {return x;}
inline VTYPE &Vector3DC::Y(void) {return y;}
inline VTYPE &Vector3DC::Z(void) {return z;}
inline VTYPE Vector3DC::W(void) {return 0;}
inline const VTYPE &Vector3DC::X(void) const {return x;}
inline const VTYPE &Vector3DC::Y(void) const {return y;}
inline const VTYPE &Vector3DC::Z(void) const {return z;}
inline const VTYPE Vector3DC::W(void) const {return 0;}
inline VTYPE *Vector3DC::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DI Code Definition
#define VNAME 3DI
#define VTYPE int
// Constructors/Destructors
inline Vector3DI::Vector3DI() {x=0; y=0; z=0;}
inline Vector3DI::~Vector3DI() {}
inline Vector3DI::Vector3DI (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DI::Vector3DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Set Functions
inline Vector3DI &Vector3DI::Set (const int xa, const int ya, const int za)
{
x = xa; y = ya; z = za;
return *this;
}
// Member Functions
inline Vector3DI &Vector3DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DI::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DI &Vector3DI::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
z = (VTYPE) (((double) z*255)/n);
}
return *this;
}
inline double Vector3DI::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DI::X(void) {return x;}
inline VTYPE &Vector3DI::Y(void) {return y;}
inline VTYPE &Vector3DI::Z(void) {return z;}
inline VTYPE Vector3DI::W(void) {return 0;}
inline const VTYPE &Vector3DI::X(void) const {return x;}
inline const VTYPE &Vector3DI::Y(void) const {return y;}
inline const VTYPE &Vector3DI::Z(void) const {return z;}
inline const VTYPE Vector3DI::W(void) const {return 0;}
inline VTYPE *Vector3DI::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DF Code Definition
#define VNAME 3DF
#define VTYPE double
// Constructors/Destructors
inline Vector3DF::Vector3DF() {x=0; y=0; z=0;}
inline Vector3DF::~Vector3DF() {}
inline Vector3DF::Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DF::Vector3DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Set Functions
inline Vector3DF &Vector3DF::Set (const double xa, const double ya, const double za)
{
x = xa; y = ya; z = za;
return *this;
}
// Member Functions
inline Vector3DF &Vector3DF::operator= (const int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator= (const double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator+= (const double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator-= (const double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator*= (const double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator/= (const double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DF::Dot(const Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dot(const Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dot(const Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::DistSq (const Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DF &Vector3DF::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x /= n; y /= n; z /= n;
}
return *this;
}
inline double Vector3DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DF::X() {return x;}
inline VTYPE &Vector3DF::Y() {return y;}
inline VTYPE &Vector3DF::Z() {return z;}
inline VTYPE Vector3DF::W() {return 0;}
inline const VTYPE &Vector3DF::X() const {return x;}
inline const VTYPE &Vector3DF::Y() const {return y;}
inline const VTYPE &Vector3DF::Z() const {return z;}
inline const VTYPE Vector3DF::W() const {return 0;}
inline VTYPE *Vector3DF::Data () {return &x;}
#undef VTYPE
#undef VNAME
// Vector4DF Code Definition
#define VNAME 4DF
#define VTYPE double
// Constructors/Destructors
inline Vector4DF::Vector4DF() {x=0; y=0; z=0; w=0;}
inline Vector4DF::~Vector4DF() {}
inline Vector4DF::Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa) {x=xa; y=ya; z=za; w=wa;}
inline Vector4DF::Vector4DF (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w;}
// Member Functions
inline Vector4DF &Vector4DF::operator= (int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator= (double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator+= (int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator+= (double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; w+=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator-= (int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator-= (double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; w-=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator*= (int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator*= (double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; w*=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator/= (int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator/= (double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; w/=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::Cross (Vector4DF &v) {double ax = x, ay = y, az = z, aw = w; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); w = (VTYPE) 0; return *this;}
inline double Vector4DF::Dot(Vector4DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z + (double) w*v.w; return dot;}
inline double Vector4DF::Dist (Vector4DF &v) {double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector4DF::DistSq (Vector4DF &v) {double a,b,c,d; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; d = (double) w - (double) v.w; return (a*a + b*b + c*c + d*d);}
inline Vector4DF &Vector4DF::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z + (double) w*w;
if (n!=0.0) {
n = sqrt(n);
x /= n; y /= n; z /= n; w /= n;
}
return *this;
}
inline double Vector4DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector4DF::X(void) {return x;}
inline VTYPE &Vector4DF::Y(void) {return y;}
inline VTYPE &Vector4DF::Z(void) {return z;}
inline VTYPE &Vector4DF::W(void) {return w;}
inline const VTYPE &Vector4DF::X(void) const {return x;}
inline const VTYPE &Vector4DF::Y(void) const {return y;}
inline const VTYPE &Vector4DF::Z(void) const {return z;}
inline const VTYPE &Vector4DF::W(void) const {return w;}
inline VTYPE *Vector4DF::Data (void) {return &x;}
#undef VTYPE
#undef VNAME

View File

@@ -0,0 +1,761 @@
// Vector Operations Implemented:
// =, +, -, *, / (on vectors and scalars)
// Cross Cross product vector with op
// Dot Dot product vector with op
// Dist (op) Distance from vector to op
// DistSq Distance^2 from vector to op
// Length () Length of vector
// Normalize () Normalizes vector
//
#include <math.h>
// Vector2DC Code Definition
#define VTYPE unsigned char
#define VNAME 2DC
// Constructors/Destructors
inline Vector2DC::Vector2DC() {x=0; y=0;}
inline Vector2DC::~Vector2DC() {}
inline Vector2DC::Vector2DC (VTYPE xa, VTYPE ya) {x=xa; y=ya;}
inline Vector2DC::Vector2DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DC::Vector2DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DC &Vector2DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DC &Vector2DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DC::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DC::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DC::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DC &Vector2DC::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
}
return *this;
}
inline double Vector2DC::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DC::X(void) {return x;}
inline VTYPE &Vector2DC::Y(void) {return y;}
inline VTYPE Vector2DC::Z(void) {return 0;}
inline VTYPE Vector2DC::W(void) {return 0;}
inline const VTYPE &Vector2DC::X(void) const {return x;}
inline const VTYPE &Vector2DC::Y(void) const {return y;}
inline const VTYPE Vector2DC::Z(void) const {return 0;}
inline const VTYPE Vector2DC::W(void) const {return 0;}
inline VTYPE *Vector2DC::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector2DI Code Definition
#define VNAME 2DI
#define VTYPE int
// Constructors/Destructors
inline Vector2DI::Vector2DI() {x=0; y=0;}
inline Vector2DI::~Vector2DI() {}
inline Vector2DI::Vector2DI (VTYPE xa, VTYPE ya) {x=xa; y=ya;}
inline Vector2DI::Vector2DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DI::Vector2DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DI &Vector2DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DI &Vector2DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DI::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DI::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DI::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DI &Vector2DI::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
}
return *this;
}
inline double Vector2DI::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DI::X(void) {return x;}
inline VTYPE &Vector2DI::Y(void) {return y;}
inline VTYPE Vector2DI::Z(void) {return 0;}
inline VTYPE Vector2DI::W(void) {return 0;}
inline const VTYPE &Vector2DI::X(void) const {return x;}
inline const VTYPE &Vector2DI::Y(void) const {return y;}
inline const VTYPE Vector2DI::Z(void) const {return 0;}
inline const VTYPE Vector2DI::W(void) const {return 0;}
inline VTYPE *Vector2DI::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector2DF Code Definition
#define VNAME 2DF
#define VTYPE double
// Constructors/Destructors
inline Vector2DF::Vector2DF() {x=0; y=0;}
inline Vector2DF::~Vector2DF() {}
inline Vector2DF::Vector2DF (const VTYPE xa, const VTYPE ya) {x=xa; y=ya;}
inline Vector2DF::Vector2DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
inline Vector2DF::Vector2DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;}
// Member Functions
inline Vector2DF &Vector2DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector2DF &Vector2DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Vector2DF::Dot(const Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dot(const Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dot(const Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;}
inline double Vector2DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector2DF::DistSq (const Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline double Vector2DF::DistSq (const Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);}
inline Vector2DF &Vector2DF::Normalize (void) {
double n = (double) x*x + (double) y*y;
if (n!=0.0) {
n = sqrt(n);
x /= n;
y /= n;
}
return *this;
}
inline double Vector2DF::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector2DF::X(void) {return x;}
inline VTYPE &Vector2DF::Y(void) {return y;}
inline VTYPE Vector2DF::Z(void) {return 0;}
inline VTYPE Vector2DF::W(void) {return 0;}
inline const VTYPE &Vector2DF::X(void) const {return x;}
inline const VTYPE &Vector2DF::Y(void) const {return y;}
inline const VTYPE Vector2DF::Z(void) const {return 0;}
inline const VTYPE Vector2DF::W(void) const {return 0;}
inline VTYPE *Vector2DF::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DC Code Definition
#define VNAME 3DC
#define VTYPE unsigned char
// Constructors/Destructors
inline Vector3DC::Vector3DC() {x=0; y=0; z=0;}
inline Vector3DC::~Vector3DC() {}
inline Vector3DC::Vector3DC (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DC::Vector3DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DC::Vector3DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DC::Vector3DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Member Functions
inline Vector3DC &Vector3DC::Set (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DC &Vector3DC::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DC::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DC::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DC::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DC &Vector3DC::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
z = (VTYPE) (((double) z*255)/n);
}
return *this;
}
inline double Vector3DC::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DC::X(void) {return x;}
inline VTYPE &Vector3DC::Y(void) {return y;}
inline VTYPE &Vector3DC::Z(void) {return z;}
inline VTYPE Vector3DC::W(void) {return 0;}
inline const VTYPE &Vector3DC::X(void) const {return x;}
inline const VTYPE &Vector3DC::Y(void) const {return y;}
inline const VTYPE &Vector3DC::Z(void) const {return z;}
inline const VTYPE Vector3DC::W(void) const {return 0;}
inline VTYPE *Vector3DC::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DI Code Definition
#define VNAME 3DI
#define VTYPE int
// Constructors/Destructors
inline Vector3DI::Vector3DI() {x=0; y=0; z=0;}
inline Vector3DI::~Vector3DI() {}
inline Vector3DI::Vector3DI (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DI::Vector3DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DI::Vector3DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DI::Vector3DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Set Functions
inline Vector3DI &Vector3DI::Set (const int xa, const int ya, const int za)
{
x = xa; y = ya; z = za;
return *this;
}
// Member Functions
inline Vector3DI &Vector3DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DI &Vector3DI::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DI::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DI::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DI::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DI &Vector3DI::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x = (VTYPE) (((double) x*255)/n);
y = (VTYPE) (((double) y*255)/n);
z = (VTYPE) (((double) z*255)/n);
}
return *this;
}
inline double Vector3DI::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DI::X(void) {return x;}
inline VTYPE &Vector3DI::Y(void) {return y;}
inline VTYPE &Vector3DI::Z(void) {return z;}
inline VTYPE Vector3DI::W(void) {return 0;}
inline const VTYPE &Vector3DI::X(void) const {return x;}
inline const VTYPE &Vector3DI::Y(void) const {return y;}
inline const VTYPE &Vector3DI::Z(void) const {return z;}
inline const VTYPE Vector3DI::W(void) const {return 0;}
inline VTYPE *Vector3DI::Data (void) {return &x;}
#undef VTYPE
#undef VNAME
// Vector3DF Code Definition
#define VNAME 3DF
#define VTYPE float
// Constructors/Destructors
inline Vector3DF::Vector3DF() {x=0; y=0; z=0;}
inline Vector3DF::~Vector3DF() {}
inline Vector3DF::Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za) {x=xa; y=ya; z=za;}
inline Vector3DF::Vector3DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;}
inline Vector3DF::Vector3DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
inline Vector3DF::Vector3DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;}
// Set Functions
inline Vector3DF &Vector3DF::Set (const double xa, const double ya, const double za)
{
x = (float) xa; y = (float) ya; z = (float) za;
return *this;
}
// Member Functions
inline Vector3DF &Vector3DF::operator= (const int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator= (const double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator+= (const double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator-= (const double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator*= (const double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator/= (const double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline Vector3DF &Vector3DF::Cross (const Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;}
inline double Vector3DF::Dot(const Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dot(const Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dot(const Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;}
inline double Vector3DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector3DF::DistSq (const Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline double Vector3DF::DistSq (const Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);}
inline Vector3DF &Vector3DF::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z;
if (n!=0.0) {
n = sqrt(n);
x /= (float) n; y /= (float) n; z /= (float) n;
}
return *this;
}
inline double Vector3DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector3DF::X() {return x;}
inline VTYPE &Vector3DF::Y() {return y;}
inline VTYPE &Vector3DF::Z() {return z;}
inline VTYPE Vector3DF::W() {return 0;}
inline const VTYPE &Vector3DF::X() const {return x;}
inline const VTYPE &Vector3DF::Y() const {return y;}
inline const VTYPE &Vector3DF::Z() const {return z;}
inline const VTYPE Vector3DF::W() const {return 0;}
inline VTYPE *Vector3DF::Data () {return &x;}
#undef VTYPE
#undef VNAME
// Vector4DF Code Definition
#define VNAME 4DF
#define VTYPE double
// Constructors/Destructors
inline Vector4DF::Vector4DF() {x=0; y=0; z=0; w=0;}
inline Vector4DF::~Vector4DF() {}
inline Vector4DF::Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa) {x=xa; y=ya; z=za; w=wa;}
inline Vector4DF::Vector4DF (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;}
inline Vector4DF::Vector4DF (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w;}
// Member Functions
inline Vector4DF &Vector4DF::operator= (int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator= (double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;}
inline Vector4DF &Vector4DF::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator+= (int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator+= (double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; w+=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator-= (int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator-= (double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; w-=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator*= (int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator*= (double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; w*=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::operator/= (int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator/= (double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;}
inline Vector4DF &Vector4DF::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; w/=(VTYPE) op.w; return *this;}
inline Vector4DF &Vector4DF::Cross (Vector4DF &v) {double ax = x, ay = y, az = z, aw = w; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); w = (VTYPE) 0; return *this;}
inline double Vector4DF::Dot(Vector4DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z + (double) w*v.w; return dot;}
inline double Vector4DF::Dist (Vector4DF &v) {double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;}
inline double Vector4DF::DistSq (Vector4DF &v) {double a,b,c,d; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; d = (double) w - (double) v.w; return (a*a + b*b + c*c + d*d);}
inline Vector4DF &Vector4DF::Normalize (void) {
double n = (double) x*x + (double) y*y + (double) z*z + (double) w*w;
if (n!=0.0) {
n = sqrt(n);
x /= n; y /= n; z /= n; w /= n;
}
return *this;
}
inline double Vector4DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; if (n != 0.0) return sqrt(n); return 0.0; }
inline VTYPE &Vector4DF::X(void) {return x;}
inline VTYPE &Vector4DF::Y(void) {return y;}
inline VTYPE &Vector4DF::Z(void) {return z;}
inline VTYPE &Vector4DF::W(void) {return w;}
inline const VTYPE &Vector4DF::X(void) const {return x;}
inline const VTYPE &Vector4DF::Y(void) const {return y;}
inline const VTYPE &Vector4DF::Z(void) const {return z;}
inline const VTYPE &Vector4DF::W(void) const {return w;}
inline VTYPE *Vector4DF::Data (void) {return &x;}
#undef VTYPE
#undef VNAME

View File

@@ -0,0 +1,70 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "vector.h"
#include "matrix.h"
Vector3DF &Vector3DF::operator*= (const MatrixF &op)
{
double *m = op.GetDataF ();
double xa, ya, za;
xa = x * (*m++); ya = x * (*m++); za = x * (*m++); m++;
xa += y * (*m++); ya += y * (*m++); za += y * (*m++); m++;
xa += z * (*m++); ya += z * (*m++); za += z * (*m++); m++;
xa += (*m++); ya += (*m++); za += (*m++);
x = (float) xa; y = (float) ya; z = (float) za;
return *this;
}
Vector3DF &Vector3DF::operator*= (const Matrix4F &op)
{
float xa, ya, za;
xa = x * op.data[0] + y * op.data[4] + z * op.data[8] + op.data[12];
ya = x * op.data[1] + y * op.data[5] + z * op.data[9] + op.data[13];
za = x * op.data[2] + y * op.data[6] + z * op.data[10] + op.data[14];
x = xa; y = ya; z = za;
return *this;
}
Vector4DF &Vector4DF::operator*= (const MatrixF &op)
{
double *m = op.GetDataF ();
double xa, ya, za, wa;
xa = x * (*m++); ya = x * (*m++); za = x * (*m++); wa = x * (*m++);
xa += y * (*m++); ya += y * (*m++); za += y * (*m++); wa += y * (*m++);
xa += z * (*m++); ya += z * (*m++); za += z * (*m++); wa += z * (*m++);
xa += w * (*m++); ya += w * (*m++); za += w * (*m++); wa += w * (*m++);
x = xa; y = ya; z = za; w = wa;
return *this;
}
Vector4DF &Vector4DF::operator*= (const Matrix4F &op)
{
double xa, ya, za, wa;
xa = x * op.data[0] + y * op.data[4] + z * op.data[8] + w * op.data[12];
ya = x * op.data[1] + y * op.data[5] + z * op.data[9] + w * op.data[13];
za = x * op.data[2] + y * op.data[6] + z * op.data[10] + w * op.data[14];
wa = x * op.data[3] + y * op.data[7] + z * op.data[11] + w * op.data[15];
x = xa; y = ya; z = za; w = wa;
return *this;
}

785
Extras/sph/common/vector.h Normal file
View File

@@ -0,0 +1,785 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// ** NOTES **
// Vector code CANNOT be inlined in header file because of dependencies
// across vector classes (error generated: "Use of undeclared class..")
//
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory.h>
#include <math.h>
#ifndef VECTOR_DEF
#define VECTOR_DEF
//#define VECTOR_INITIALIZE // Initializes vectors
class Vector2DC; // Forward Referencing
class Vector2DI;
class Vector2DF;
class Vector3DC;
class Vector3DI;
class Vector3DF;
class Vector4DF;
class MatrixF;
class Matrix4F;
// Vector2DC Declaration
#define VNAME 2DC
#define VTYPE unsigned char
class Vector2DC {
public:
VTYPE x, y;
// Constructors/Destructors
inline Vector2DC();
inline ~Vector2DC();
inline Vector2DC (VTYPE xa, VTYPE ya);
inline Vector2DC (Vector2DC &op);
inline Vector2DC (Vector2DI &op);
inline Vector2DC (Vector2DF &op);
inline Vector2DC (Vector3DC &op);
inline Vector2DC (Vector3DI &op);
inline Vector2DC (Vector3DF &op);
inline Vector2DC (Vector4DF &op);
// Member Functions
inline Vector2DC &operator= (Vector2DC &op);
inline Vector2DC &operator= (Vector2DI &op);
inline Vector2DC &operator= (Vector2DF &op);
inline Vector2DC &operator= (Vector3DC &op);
inline Vector2DC &operator= (Vector3DI &op);
inline Vector2DC &operator= (Vector3DF &op);
inline Vector2DC &operator= (Vector4DF &op);
inline Vector2DC &operator+= (Vector2DC &op);
inline Vector2DC &operator+= (Vector2DI &op);
inline Vector2DC &operator+= (Vector2DF &op);
inline Vector2DC &operator+= (Vector3DC &op);
inline Vector2DC &operator+= (Vector3DI &op);
inline Vector2DC &operator+= (Vector3DF &op);
inline Vector2DC &operator+= (Vector4DF &op);
inline Vector2DC &operator-= (Vector2DC &op);
inline Vector2DC &operator-= (Vector2DI &op);
inline Vector2DC &operator-= (Vector2DF &op);
inline Vector2DC &operator-= (Vector3DC &op);
inline Vector2DC &operator-= (Vector3DI &op);
inline Vector2DC &operator-= (Vector3DF &op);
inline Vector2DC &operator-= (Vector4DF &op);
inline Vector2DC &operator*= (Vector2DC &op);
inline Vector2DC &operator*= (Vector2DI &op);
inline Vector2DC &operator*= (Vector2DF &op);
inline Vector2DC &operator*= (Vector3DC &op);
inline Vector2DC &operator*= (Vector3DI &op);
inline Vector2DC &operator*= (Vector3DF &op);
inline Vector2DC &operator*= (Vector4DF &op);
inline Vector2DC &operator/= (Vector2DC &op);
inline Vector2DC &operator/= (Vector2DI &op);
inline Vector2DC &operator/= (Vector2DF &op);
inline Vector2DC &operator/= (Vector3DC &op);
inline Vector2DC &operator/= (Vector3DI &op);
inline Vector2DC &operator/= (Vector3DF &op);
inline Vector2DC &operator/= (Vector4DF &op);
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Dot(Vector2DC &v);
inline double Dot(Vector2DI &v);
inline double Dot(Vector2DF &v);
inline double Dist (Vector2DC &v);
inline double Dist (Vector2DI &v);
inline double Dist (Vector2DF &v);
inline double Dist (Vector3DC &v);
inline double Dist (Vector3DI &v);
inline double Dist (Vector3DF &v);
inline double Dist (Vector4DF &v);
inline double DistSq (Vector2DC &v);
inline double DistSq (Vector2DI &v);
inline double DistSq (Vector2DF &v);
inline double DistSq (Vector3DC &v);
inline double DistSq (Vector3DI &v);
inline double DistSq (Vector3DF &v);
inline double DistSq (Vector4DF &v);
inline Vector2DC &Normalize (void);
inline double Length (void);
inline VTYPE &X(void);
inline VTYPE &Y(void);
inline VTYPE Z(void);
inline VTYPE W(void);
inline const VTYPE &X(void) const;
inline const VTYPE &Y(void) const;
inline const VTYPE Z(void) const;
inline const VTYPE W(void) const;
inline VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector2DI Declaration
#define VNAME 2DI
#define VTYPE int
class Vector2DI {
public:
VTYPE x, y;
// Constructors/Destructors
inline Vector2DI();
inline ~Vector2DI();
inline Vector2DI (VTYPE xa, VTYPE ya);
inline Vector2DI (Vector2DC &op);
inline Vector2DI (Vector2DI &op);
inline Vector2DI (Vector2DF &op);
inline Vector2DI (Vector3DC &op);
inline Vector2DI (Vector3DI &op);
inline Vector2DI (Vector3DF &op);
inline Vector2DI (Vector4DF &op);
// Member Functions
inline Vector2DI &operator= (Vector2DC &op);
inline Vector2DI &operator= (Vector2DI &op);
inline Vector2DI &operator= (Vector2DF &op);
inline Vector2DI &operator= (Vector3DC &op);
inline Vector2DI &operator= (Vector3DI &op);
inline Vector2DI &operator= (Vector3DF &op);
inline Vector2DI &operator= (Vector4DF &op);
inline Vector2DI &operator+= (Vector2DC &op);
inline Vector2DI &operator+= (Vector2DI &op);
inline Vector2DI &operator+= (Vector2DF &op);
inline Vector2DI &operator+= (Vector3DC &op);
inline Vector2DI &operator+= (Vector3DI &op);
inline Vector2DI &operator+= (Vector3DF &op);
inline Vector2DI &operator+= (Vector4DF &op);
inline Vector2DI &operator-= (Vector2DC &op);
inline Vector2DI &operator-= (Vector2DI &op);
inline Vector2DI &operator-= (Vector2DF &op);
inline Vector2DI &operator-= (Vector3DC &op);
inline Vector2DI &operator-= (Vector3DI &op);
inline Vector2DI &operator-= (Vector3DF &op);
inline Vector2DI &operator-= (Vector4DF &op);
inline Vector2DI &operator*= (Vector2DC &op);
inline Vector2DI &operator*= (Vector2DI &op);
inline Vector2DI &operator*= (Vector2DF &op);
inline Vector2DI &operator*= (Vector3DC &op);
inline Vector2DI &operator*= (Vector3DI &op);
inline Vector2DI &operator*= (Vector3DF &op);
inline Vector2DI &operator*= (Vector4DF &op);
inline Vector2DI &operator/= (Vector2DC &op);
inline Vector2DI &operator/= (Vector2DI &op);
inline Vector2DI &operator/= (Vector2DF &op);
inline Vector2DI &operator/= (Vector3DC &op);
inline Vector2DI &operator/= (Vector3DI &op);
inline Vector2DI &operator/= (Vector3DF &op);
inline Vector2DI &operator/= (Vector4DF &op);
// Note: Cross product does not exist for 2D vectors (only 3D)
inline double Dot(Vector2DC &v);
inline double Dot(Vector2DI &v);
inline double Dot(Vector2DF &v);
inline double Dist (Vector2DC &v);
inline double Dist (Vector2DI &v);
inline double Dist (Vector2DF &v);
inline double Dist (Vector3DC &v);
inline double Dist (Vector3DI &v);
inline double Dist (Vector3DF &v);
inline double Dist (Vector4DF &v);
inline double DistSq (Vector2DC &v);
inline double DistSq (Vector2DI &v);
inline double DistSq (Vector2DF &v);
inline double DistSq (Vector3DC &v);
inline double DistSq (Vector3DI &v);
inline double DistSq (Vector3DF &v);
inline double DistSq (Vector4DF &v);
inline Vector2DI &Normalize (void);
inline double Length (void);
inline VTYPE &X(void);
inline VTYPE &Y(void);
inline VTYPE Z(void);
inline VTYPE W(void);
inline const VTYPE &X(void) const;
inline const VTYPE &Y(void) const;
inline const VTYPE Z(void) const;
inline const VTYPE W(void) const;
inline VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector2DF Declarations
#define VNAME 2DF
#define VTYPE double
class Vector2DF {
public:
VTYPE x, y;
// Constructors/Destructors
Vector2DF ();
~Vector2DF ();
Vector2DF (const VTYPE xa, const VTYPE ya);
Vector2DF (const Vector2DC &op);
Vector2DF (const Vector2DI &op);
Vector2DF (const Vector2DF &op);
Vector2DF (const Vector3DC &op);
Vector2DF (const Vector3DI &op);
Vector2DF (const Vector3DF &op);
Vector2DF (const Vector4DF &op);
// Member Functions
Vector2DF &operator= (const Vector2DC &op);
Vector2DF &operator= (const Vector2DI &op);
Vector2DF &operator= (const Vector2DF &op);
Vector2DF &operator= (const Vector3DC &op);
Vector2DF &operator= (const Vector3DI &op);
Vector2DF &operator= (const Vector3DF &op);
Vector2DF &operator= (const Vector4DF &op);
Vector2DF &operator+= (const Vector2DC &op);
Vector2DF &operator+= (const Vector2DI &op);
Vector2DF &operator+= (const Vector2DF &op);
Vector2DF &operator+= (const Vector3DC &op);
Vector2DF &operator+= (const Vector3DI &op);
Vector2DF &operator+= (const Vector3DF &op);
Vector2DF &operator+= (const Vector4DF &op);
Vector2DF &operator-= (const Vector2DC &op);
Vector2DF &operator-= (const Vector2DI &op);
Vector2DF &operator-= (const Vector2DF &op);
Vector2DF &operator-= (const Vector3DC &op);
Vector2DF &operator-= (const Vector3DI &op);
Vector2DF &operator-= (const Vector3DF &op);
Vector2DF &operator-= (const Vector4DF &op);
Vector2DF &operator*= (const Vector2DC &op);
Vector2DF &operator*= (const Vector2DI &op);
Vector2DF &operator*= (const Vector2DF &op);
Vector2DF &operator*= (const Vector3DC &op);
Vector2DF &operator*= (const Vector3DI &op);
Vector2DF &operator*= (const Vector3DF &op);
Vector2DF &operator*= (const Vector4DF &op);
Vector2DF &operator/= (const Vector2DC &op);
Vector2DF &operator/= (const Vector2DI &op);
Vector2DF &operator/= (const Vector2DF &op);
Vector2DF &operator/= (const Vector3DC &op);
Vector2DF &operator/= (const Vector3DI &op);
Vector2DF &operator/= (const Vector3DF &op);
Vector2DF &operator/= (const Vector4DF &op);
Vector2DF &operator/= (const double v) {x /= v; y /= v; return *this;}
// Note: Cross product does not exist for 2D vectors (only 3D)
double Dot(const Vector2DC &v);
double Dot(const Vector2DI &v);
double Dot(const Vector2DF &v);
double Dist (const Vector2DC &v);
double Dist (const Vector2DI &v);
double Dist (const Vector2DF &v);
double Dist (const Vector3DC &v);
double Dist (const Vector3DI &v);
double Dist (const Vector3DF &v);
double Dist (const Vector4DF &v);
double DistSq (const Vector2DC &v);
double DistSq (const Vector2DI &v);
double DistSq (const Vector2DF &v);
double DistSq (const Vector3DC &v);
double DistSq (const Vector3DI &v);
double DistSq (const Vector3DF &v);
double DistSq (const Vector4DF &v);
Vector2DF &Normalize (void);
double Length (void);
VTYPE &X(void);
VTYPE &Y(void);
VTYPE Z(void);
VTYPE W(void);
const VTYPE &X(void) const;
const VTYPE &Y(void) const;
const VTYPE Z(void) const;
const VTYPE W(void) const;
VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector3DC Declaration
#define VNAME 3DC
#define VTYPE unsigned char
class Vector3DC {
public:
VTYPE x, y, z;
// Constructors/Destructors
inline Vector3DC();
inline ~Vector3DC();
inline Vector3DC (VTYPE xa, VTYPE ya, VTYPE za);
inline Vector3DC (Vector2DC &op);
inline Vector3DC (Vector2DI &op);
inline Vector3DC (Vector2DF &op);
inline Vector3DC (Vector3DC &op);
inline Vector3DC (Vector3DI &op);
inline Vector3DC (Vector3DF &op);
inline Vector3DC (Vector4DF &op);
// Member Functions
inline Vector3DC &Set (VTYPE xa, VTYPE ya, VTYPE za);
inline Vector3DC &operator= (Vector2DC &op);
inline Vector3DC &operator= (Vector2DI &op);
inline Vector3DC &operator= (Vector2DF &op);
inline Vector3DC &operator= (Vector3DC &op);
inline Vector3DC &operator= (Vector3DI &op);
inline Vector3DC &operator= (Vector3DF &op);
inline Vector3DC &operator= (Vector4DF &op);
inline Vector3DC &operator+= (Vector2DC &op);
inline Vector3DC &operator+= (Vector2DI &op);
inline Vector3DC &operator+= (Vector2DF &op);
inline Vector3DC &operator+= (Vector3DC &op);
inline Vector3DC &operator+= (Vector3DI &op);
inline Vector3DC &operator+= (Vector3DF &op);
inline Vector3DC &operator+= (Vector4DF &op);
inline Vector3DC &operator-= (Vector2DC &op);
inline Vector3DC &operator-= (Vector2DI &op);
inline Vector3DC &operator-= (Vector2DF &op);
inline Vector3DC &operator-= (Vector3DC &op);
inline Vector3DC &operator-= (Vector3DI &op);
inline Vector3DC &operator-= (Vector3DF &op);
inline Vector3DC &operator-= (Vector4DF &op);
inline Vector3DC &operator*= (Vector2DC &op);
inline Vector3DC &operator*= (Vector2DI &op);
inline Vector3DC &operator*= (Vector2DF &op);
inline Vector3DC &operator*= (Vector3DC &op);
inline Vector3DC &operator*= (Vector3DI &op);
inline Vector3DC &operator*= (Vector3DF &op);
inline Vector3DC &operator*= (Vector4DF &op);
inline Vector3DC &operator/= (Vector2DC &op);
inline Vector3DC &operator/= (Vector2DI &op);
inline Vector3DC &operator/= (Vector2DF &op);
inline Vector3DC &operator/= (Vector3DC &op);
inline Vector3DC &operator/= (Vector3DI &op);
inline Vector3DC &operator/= (Vector3DF &op);
inline Vector3DC &operator/= (Vector4DF &op);
inline Vector3DC &Cross (Vector3DC &v);
inline Vector3DC &Cross (Vector3DI &v);
inline Vector3DC &Cross (Vector3DF &v);
inline double Dot(Vector3DC &v);
inline double Dot(Vector3DI &v);
inline double Dot(Vector3DF &v);
inline double Dist (Vector2DC &v);
inline double Dist (Vector2DI &v);
inline double Dist (Vector2DF &v);
inline double Dist (Vector3DC &v);
inline double Dist (Vector3DI &v);
inline double Dist (Vector3DF &v);
inline double Dist (Vector4DF &v);
inline double DistSq (Vector2DC &v);
inline double DistSq (Vector2DI &v);
inline double DistSq (Vector2DF &v);
inline double DistSq (Vector3DC &v);
inline double DistSq (Vector3DI &v);
inline double DistSq (Vector3DF &v);
inline double DistSq (Vector4DF &v);
inline Vector3DC &Normalize (void);
inline double Length (void);
inline VTYPE &X(void);
inline VTYPE &Y(void);
inline VTYPE &Z(void);
inline VTYPE W(void);
inline const VTYPE &X(void) const;
inline const VTYPE &Y(void) const;
inline const VTYPE &Z(void) const;
inline const VTYPE W(void) const;
inline VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector3DI Declaration
#define VNAME 3DI
#define VTYPE int
class Vector3DI {
public:
VTYPE x, y, z;
// Constructors/Destructors
inline Vector3DI();
inline ~Vector3DI();
inline Vector3DI (VTYPE xa, VTYPE ya, VTYPE za);
inline Vector3DI (Vector2DC &op);
inline Vector3DI (Vector2DI &op);
inline Vector3DI (Vector2DF &op);
inline Vector3DI (Vector3DC &op);
inline Vector3DI (Vector3DI &op);
inline Vector3DI (Vector3DF &op);
inline Vector3DI (Vector4DF &op);
// Set Functions
inline Vector3DI &Set (const int xa, const int ya, const int za);
// Member Functions
inline Vector3DI &operator= (Vector2DC &op);
inline Vector3DI &operator= (Vector2DI &op);
inline Vector3DI &operator= (Vector2DF &op);
inline Vector3DI &operator= (Vector3DC &op);
inline Vector3DI &operator= (Vector3DI &op);
inline Vector3DI &operator= (Vector3DF &op);
inline Vector3DI &operator= (Vector4DF &op);
inline Vector3DI &operator+= (Vector2DC &op);
inline Vector3DI &operator+= (Vector2DI &op);
inline Vector3DI &operator+= (Vector2DF &op);
inline Vector3DI &operator+= (Vector3DC &op);
inline Vector3DI &operator+= (Vector3DI &op);
inline Vector3DI &operator+= (Vector3DF &op);
inline Vector3DI &operator+= (Vector4DF &op);
inline Vector3DI &operator-= (Vector2DC &op);
inline Vector3DI &operator-= (Vector2DI &op);
inline Vector3DI &operator-= (Vector2DF &op);
inline Vector3DI &operator-= (Vector3DC &op);
inline Vector3DI &operator-= (Vector3DI &op);
inline Vector3DI &operator-= (Vector3DF &op);
inline Vector3DI &operator-= (Vector4DF &op);
inline Vector3DI &operator*= (Vector2DC &op);
inline Vector3DI &operator*= (Vector2DI &op);
inline Vector3DI &operator*= (Vector2DF &op);
inline Vector3DI &operator*= (Vector3DC &op);
inline Vector3DI &operator*= (Vector3DI &op);
inline Vector3DI &operator*= (Vector3DF &op);
inline Vector3DI &operator*= (Vector4DF &op);
inline Vector3DI &operator/= (Vector2DC &op);
inline Vector3DI &operator/= (Vector2DI &op);
inline Vector3DI &operator/= (Vector2DF &op);
inline Vector3DI &operator/= (Vector3DC &op);
inline Vector3DI &operator/= (Vector3DI &op);
inline Vector3DI &operator/= (Vector3DF &op);
inline Vector3DI &operator/= (Vector4DF &op);
inline Vector3DI &Cross (Vector3DC &v);
inline Vector3DI &Cross (Vector3DI &v);
inline Vector3DI &Cross (Vector3DF &v);
inline double Dot(Vector3DC &v);
inline double Dot(Vector3DI &v);
inline double Dot(Vector3DF &v);
inline double Dist (Vector2DC &v);
inline double Dist (Vector2DI &v);
inline double Dist (Vector2DF &v);
inline double Dist (Vector3DC &v);
inline double Dist (Vector3DI &v);
inline double Dist (Vector3DF &v);
inline double Dist (Vector4DF &v);
inline double DistSq (Vector2DC &v);
inline double DistSq (Vector2DI &v);
inline double DistSq (Vector2DF &v);
inline double DistSq (Vector3DC &v);
inline double DistSq (Vector3DI &v);
inline double DistSq (Vector3DF &v);
inline double DistSq (Vector4DF &v);
inline Vector3DI &Normalize (void);
inline double Length (void);
inline VTYPE &X(void);
inline VTYPE &Y(void);
inline VTYPE &Z(void);
inline VTYPE W(void);
inline const VTYPE &X(void) const;
inline const VTYPE &Y(void) const;
inline const VTYPE &Z(void) const;
inline const VTYPE W(void) const;
inline VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector3DF Declarations
#define VNAME 3DF
#define VTYPE float
class Vector3DF {
public:
VTYPE x, y, z;
// Constructors/Destructors
inline Vector3DF();
inline ~Vector3DF();
inline Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za);
inline Vector3DF (const Vector2DC &op);
inline Vector3DF (const Vector2DI &op);
inline Vector3DF (const Vector2DF &op);
inline Vector3DF (const Vector3DC &op);
inline Vector3DF (const Vector3DI &op);
inline Vector3DF (const Vector3DF &op);
inline Vector3DF (const Vector4DF &op);
// Set Functions
inline Vector3DF &Set (const double xa, const double ya, const double za);
// Member Functions
inline Vector3DF &operator= (const int op);
inline Vector3DF &operator= (const double op);
inline Vector3DF &operator= (const Vector2DC &op);
inline Vector3DF &operator= (const Vector2DI &op);
inline Vector3DF &operator= (const Vector2DF &op);
inline Vector3DF &operator= (const Vector3DC &op);
inline Vector3DF &operator= (const Vector3DI &op);
inline Vector3DF &operator= (const Vector3DF &op);
inline Vector3DF &operator= (const Vector4DF &op);
inline Vector3DF &operator+= (const int op);
inline Vector3DF &operator+= (const double op);
inline Vector3DF &operator+= (const Vector2DC &op);
inline Vector3DF &operator+= (const Vector2DI &op);
inline Vector3DF &operator+= (const Vector2DF &op);
inline Vector3DF &operator+= (const Vector3DC &op);
inline Vector3DF &operator+= (const Vector3DI &op);
inline Vector3DF &operator+= (const Vector3DF &op);
inline Vector3DF &operator+= (const Vector4DF &op);
inline Vector3DF &operator-= (const int op);
inline Vector3DF &operator-= (const double op);
inline Vector3DF &operator-= (const Vector2DC &op);
inline Vector3DF &operator-= (const Vector2DI &op);
inline Vector3DF &operator-= (const Vector2DF &op);
inline Vector3DF &operator-= (const Vector3DC &op);
inline Vector3DF &operator-= (const Vector3DI &op);
inline Vector3DF &operator-= (const Vector3DF &op);
inline Vector3DF &operator-= (const Vector4DF &op);
inline Vector3DF &operator*= (const int op);
inline Vector3DF &operator*= (const double op);
inline Vector3DF &operator*= (const Vector2DC &op);
inline Vector3DF &operator*= (const Vector2DI &op);
inline Vector3DF &operator*= (const Vector2DF &op);
inline Vector3DF &operator*= (const Vector3DC &op);
inline Vector3DF &operator*= (const Vector3DI &op);
inline Vector3DF &operator*= (const Vector3DF &op);
inline Vector3DF &operator*= (const Vector4DF &op);
Vector3DF &operator*= (const Matrix4F &op);
Vector3DF &operator*= (const MatrixF &op); // see vector.cpp
inline Vector3DF &operator/= (const int op);
inline Vector3DF &operator/= (const double op);
inline Vector3DF &operator/= (const Vector2DC &op);
inline Vector3DF &operator/= (const Vector2DI &op);
inline Vector3DF &operator/= (const Vector2DF &op);
inline Vector3DF &operator/= (const Vector3DC &op);
inline Vector3DF &operator/= (const Vector3DI &op);
inline Vector3DF &operator/= (const Vector3DF &op);
inline Vector3DF &operator/= (const Vector4DF &op);
inline Vector3DF &Cross (const Vector3DC &v);
inline Vector3DF &Cross (const Vector3DI &v);
inline Vector3DF &Cross (const Vector3DF &v);
inline double Dot(const Vector3DC &v);
inline double Dot(const Vector3DI &v);
inline double Dot(const Vector3DF &v);
inline double Dist (const Vector2DC &v);
inline double Dist (const Vector2DI &v);
inline double Dist (const Vector2DF &v);
inline double Dist (const Vector3DC &v);
inline double Dist (const Vector3DI &v);
inline double Dist (const Vector3DF &v);
inline double Dist (const Vector4DF &v);
inline double DistSq (const Vector2DC &v);
inline double DistSq (const Vector2DI &v);
inline double DistSq (const Vector2DF &v);
inline double DistSq (const Vector3DC &v);
inline double DistSq (const Vector3DI &v);
inline double DistSq (const Vector3DF &v);
inline double DistSq (const Vector4DF &v);
inline Vector3DF &Normalize (void);
inline double Length (void);
inline VTYPE &X();
inline VTYPE &Y();
inline VTYPE &Z();
inline VTYPE W();
inline const VTYPE &X() const;
inline const VTYPE &Y() const;
inline const VTYPE &Z() const;
inline const VTYPE W() const;
inline VTYPE *Data ();
};
#undef VNAME
#undef VTYPE
// Vector4DF Declarations
#define VNAME 4DF
#define VTYPE double
class Vector4DF {
public:
VTYPE x, y, z, w;
// Constructors/Destructors
inline Vector4DF();
inline ~Vector4DF();
inline Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa);
inline Vector4DF (Vector2DC &op);
inline Vector4DF (Vector2DI &op);
inline Vector4DF (Vector2DF &op);
inline Vector4DF (Vector3DC &op);
inline Vector4DF (Vector3DI &op);
inline Vector4DF (Vector3DF &op);
inline Vector4DF (Vector4DF &op);
// Member Functions
inline Vector4DF &operator= (int op);
inline Vector4DF &operator= (double op);
inline Vector4DF &operator= (Vector2DC &op);
inline Vector4DF &operator= (Vector2DI &op);
inline Vector4DF &operator= (Vector2DF &op);
inline Vector4DF &operator= (Vector3DC &op);
inline Vector4DF &operator= (Vector3DI &op);
inline Vector4DF &operator= (Vector3DF &op);
inline Vector4DF &operator= (Vector4DF &op);
inline Vector4DF &operator+= (int op);
inline Vector4DF &operator+= (double op);
inline Vector4DF &operator+= (Vector2DC &op);
inline Vector4DF &operator+= (Vector2DI &op);
inline Vector4DF &operator+= (Vector2DF &op);
inline Vector4DF &operator+= (Vector3DC &op);
inline Vector4DF &operator+= (Vector3DI &op);
inline Vector4DF &operator+= (Vector3DF &op);
inline Vector4DF &operator+= (Vector4DF &op);
inline Vector4DF &operator-= (int op);
inline Vector4DF &operator-= (double op);
inline Vector4DF &operator-= (Vector2DC &op);
inline Vector4DF &operator-= (Vector2DI &op);
inline Vector4DF &operator-= (Vector2DF &op);
inline Vector4DF &operator-= (Vector3DC &op);
inline Vector4DF &operator-= (Vector3DI &op);
inline Vector4DF &operator-= (Vector3DF &op);
inline Vector4DF &operator-= (Vector4DF &op);
inline Vector4DF &operator*= (int op);
inline Vector4DF &operator*= (double op);
inline Vector4DF &operator*= (Vector2DC &op);
inline Vector4DF &operator*= (Vector2DI &op);
inline Vector4DF &operator*= (Vector2DF &op);
inline Vector4DF &operator*= (Vector3DC &op);
inline Vector4DF &operator*= (Vector3DI &op);
inline Vector4DF &operator*= (Vector3DF &op);
inline Vector4DF &operator*= (Vector4DF &op);
Vector4DF &operator*= (const Matrix4F &op);
Vector4DF &operator*= (const MatrixF &op); // see vector.cpp
inline Vector4DF &operator/= (int op);
inline Vector4DF &operator/= (double op);
inline Vector4DF &operator/= (Vector2DC &op);
inline Vector4DF &operator/= (Vector2DI &op);
inline Vector4DF &operator/= (Vector2DF &op);
inline Vector4DF &operator/= (Vector3DC &op);
inline Vector4DF &operator/= (Vector3DI &op);
inline Vector4DF &operator/= (Vector3DF &op);
inline Vector4DF &operator/= (Vector4DF &op);
inline Vector4DF &Cross (Vector4DF &v);
inline double Dot(Vector4DF &v);
inline double Dist (Vector4DF &v);
inline double DistSq (Vector4DF &v);
inline Vector4DF &Normalize (void);
inline double Length (void);
inline VTYPE &X(void);
inline VTYPE &Y(void);
inline VTYPE &Z(void);
inline VTYPE &W(void);
inline const VTYPE &X(void) const;
inline const VTYPE &Y(void) const;
inline const VTYPE &Z(void) const;
inline const VTYPE &W(void) const;
inline VTYPE *Data (void);
};
#undef VNAME
#undef VTYPE
// Vector Code Definitions (Inlined)
#include "vector.cci"
#endif

View File

@@ -0,0 +1 @@
--import sRadixSum,%laneid,%ctaid,%nctaid,%smid,A7,%pm3,%pm2,%pm1,__CC-temp__0__,%pm0,%tid,%clock,%warpid,%ntid,%gridid --export _Z8RadixSumP12KeyValuePairjjj,_Z13hashParticlesPcP5uint2i,_Z15insertParticlesPcP5uint2Piii,_Z15computePressurePcPiP5uint2i,_Z25RadixAddOffsetsAndShuffleP12KeyValuePairS0_jji,_Z20insertParticlesRadixPcP5uint2PiS_ii,_Z12computeForcePcPiP5uint2i,_Z15computeForceNbrPci,_Z16advanceParticlesPciff,_Z14RadixPrefixSumv

302
Extras/sph/fluids.vcproj Normal file
View File

@@ -0,0 +1,302 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="fluids"
ProjectGUID="{F9F0795D-4C39-41F4-9381-25C616D69FB2}"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="common;fluids;marching;sphere_scan;marching_tris"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="glee_2008d.lib"
OutputFile="$(OutDir)/fluids_debug.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;C:\Program Files\NVIDIA Corporation\Cg\lib&quot;"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/cgdemo.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="fluids;common;marching;sphere_scan;marching_tris"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="glee_2008.lib"
OutputFile="$(OutDir)/fluids.exe"
LinkIncremental="1"
IgnoreDefaultLibraryNames="libcmtd.lib"
GenerateDebugInformation="false"
SubSystem="1"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="fluids"
>
<File
RelativePath=".\fluids\fluid.cpp"
>
</File>
<File
RelativePath=".\fluids\fluid.h"
>
</File>
<File
RelativePath=".\fluids\fluid_system.cpp"
>
</File>
<File
RelativePath=".\fluids\fluid_system.h"
>
</File>
</Filter>
<Filter
Name="common"
>
<File
RelativePath=".\common\common_defs.h"
>
</File>
<File
RelativePath=".\common\geomx.cpp"
>
</File>
<File
RelativePath=".\common\geomx.h"
>
</File>
<File
RelativePath=".\common\gl_helper.cpp"
>
</File>
<File
RelativePath=".\common\gl_helper.h"
>
</File>
<File
RelativePath=".\common\image.cpp"
>
</File>
<File
RelativePath=".\common\image.h"
>
</File>
<File
RelativePath=".\common\matrix-inline.h"
>
</File>
<File
RelativePath=".\common\matrix.cci"
>
</File>
<File
RelativePath=".\common\matrix.cpp"
>
</File>
<File
RelativePath=".\common\matrix.h"
>
</File>
<File
RelativePath=".\common\mdebug.cpp"
>
</File>
<File
RelativePath=".\common\mdebug.h"
>
</File>
<File
RelativePath=".\common\mtime.cpp"
>
</File>
<File
RelativePath=".\common\mtime.h"
>
</File>
<File
RelativePath=".\common\point_set.cpp"
>
</File>
<File
RelativePath=".\common\point_set.h"
>
</File>
<File
RelativePath=".\common\vector-inline.h"
>
</File>
<File
RelativePath=".\common\vector.cci"
>
</File>
<File
RelativePath=".\common\vector.cpp"
>
</File>
<File
RelativePath=".\common\vector.h"
>
</File>
</Filter>
<File
RelativePath=".\main.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,22 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "fluid.h"

44
Extras/sph/fluids/fluid.h Normal file
View File

@@ -0,0 +1,44 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_FLUID
#define DEF_FLUID
#include "vector.h"
#include "common_defs.h"
struct Fluid {
public:
Vector3DF pos; // Basic particle (must match Particle class)
DWORD clr;
int next;
Vector3DF vel;
Vector3DF vel_eval;
unsigned short age;
float pressure; // Smoothed Particle Hydrodynamics
float density;
Vector3DF sph_force;
};
#endif /*PARTICLE_H_*/

View File

@@ -0,0 +1,869 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <conio.h>
#ifdef _MSC_VER
#include <gl/glut.h>
#else
#include <GL/glut.h>
#endif
#include "common_defs.h"
#include "mtime.h"
#include "fluid_system.h"
#ifdef BUILD_CUDA
#include "fluid_system_host.cuh"
#endif
#define EPSILON 0.00001f //for collision detection
FluidSystem::FluidSystem ()
{
}
void FluidSystem::Initialize ( int mode, int total )
{
if ( mode != BFLUID ) {
printf ( "ERROR: FluidSystem not initialized as BFLUID.\n");
}
PointSet::Initialize ( mode, total );
FreeBuffers ();
AddBuffer ( BFLUID, sizeof ( Fluid ), total );
AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "color", sizeof ( DWORD ), false );
AddAttribute ( 0, "vel", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "ndx", sizeof ( unsigned short ), false );
AddAttribute ( 0, "age", sizeof ( unsigned short ), false );
AddAttribute ( 0, "pressure", sizeof ( double ), false );
AddAttribute ( 0, "density", sizeof ( double ), false );
AddAttribute ( 0, "sph_force", sizeof ( Vector3DF ), false );
AddAttribute ( 0, "next", sizeof ( Fluid* ), false );
AddAttribute ( 0, "tag", sizeof ( bool ), false );
SPH_Setup ();
Reset ( total );
}
void FluidSystem::Reset ( int nmax )
{
ResetBuffer ( 0, nmax );
m_DT = 0.003; // 0.001; // .001 = for point grav
// Reset parameters
m_Param [ MAX_FRAC ] = 1.0;
m_Param [ POINT_GRAV ] = 0.0;
m_Param [ PLANE_GRAV ] = 1.0;
m_Param [ BOUND_ZMIN_SLOPE ] = 0.0;
m_Param [ FORCE_XMAX_SIN ] = 0.0;
m_Param [ FORCE_XMIN_SIN ] = 0.0;
m_Toggle [ WRAP_X ] = false;
m_Toggle [ WALL_BARRIER ] = false;
m_Toggle [ LEVY_BARRIER ] = false;
m_Toggle [ DRAIN_BARRIER ] = false;
m_Param [ SPH_INTSTIFF ] = 1.00;
m_Param [ SPH_VISC ] = 0.2;
m_Param [ SPH_INTSTIFF ] = 0.50;
m_Param [ SPH_EXTSTIFF ] = 20000;
m_Param [ SPH_SMOOTHRADIUS ] = 0.01;
m_Vec [ POINT_GRAV_POS ].Set ( 0, 0, 50 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, -9.8 );
m_Vec [ EMIT_POS ].Set ( 0, 0, 0 );
m_Vec [ EMIT_RATE ].Set ( 0, 0, 0 );
m_Vec [ EMIT_ANG ].Set ( 0, 90, 1.0 );
m_Vec [ EMIT_DANG ].Set ( 0, 0, 0 );
}
int FluidSystem::AddPoint ()
{
xref ndx;
Fluid* f = (Fluid*) AddElem ( 0, ndx );
f->sph_force.Set(0,0,0);
f->vel.Set(0,0,0);
f->vel_eval.Set(0,0,0);
f->next = 0x0;
f->pressure = 0;
f->density = 0;
return ndx;
}
int FluidSystem::AddPointReuse ()
{
xref ndx;
Fluid* f;
if ( NumPoints() <= mBuf[0].max-2 )
f = (Fluid*) AddElem ( 0, ndx );
else
f = (Fluid*) RandomElem ( 0, ndx );
f->sph_force.Set(0,0,0);
f->vel.Set(0,0,0);
f->vel_eval.Set(0,0,0);
f->next = 0x0;
f->pressure = 0;
f->density = 0;
return ndx;
}
void FluidSystem::Run ()
{
bool bTiming = true;
mint::Time start, stop;
float ss = m_Param [ SPH_PDIST ] / m_Param[ SPH_SIMSCALE ]; // simulation scale (not Schutzstaffel)
if ( m_Vec[EMIT_RATE].x > 0 && (++m_Frame) % (int) m_Vec[EMIT_RATE].x == 0 ) {
//m_Frame = 0;
Emit ( ss );
}
#ifdef NOGRID
// Slow method - O(n^2)
SPH_ComputePressureSlow ();
SPH_ComputeForceSlow ();
#else
if ( m_Toggle[USE_CUDA] ) {
#ifdef BUILD_CUDA
// -- GPU --
start.SetSystemTime ( ACC_NSEC );
TransferToCUDA ( mBuf[0].data, (int*) &m_Grid[0], NumPoints() );
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "TO: %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
Grid_InsertParticlesCUDA ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "INSERT (CUDA): %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
SPH_ComputePressureCUDA ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "PRESS (CUDA): %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
SPH_ComputeForceCUDA ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FORCE (CUDA): %s\n", stop.GetReadableTime().c_str() ); }
//** CUDA integrator is incomplete..
// Once integrator is done, we can remove TransferTo/From steps
/*start.SetSystemTime ( ACC_NSEC );
SPH_AdvanceCUDA( m_DT, m_DT/m_Param[SPH_SIMSCALE] );
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "ADV (CUDA): %s\n", stop.GetReadableTime().c_str() ); }*/
start.SetSystemTime ( ACC_NSEC );
TransferFromCUDA ( mBuf[0].data, (int*) &m_Grid[0], NumPoints() );
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FROM: %s\n", stop.GetReadableTime().c_str() ); }
// .. Do advance on CPU
Advance();
#endif
} else {
// -- CPU only --
start.SetSystemTime ( ACC_NSEC );
Grid_InsertParticles ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "INSERT: %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
SPH_ComputePressureGrid ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "PRESS: %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
SPH_ComputeForceGridNC ();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FORCE: %s\n", stop.GetReadableTime().c_str() ); }
start.SetSystemTime ( ACC_NSEC );
Advance();
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "ADV: %s\n", stop.GetReadableTime().c_str() ); }
}
#endif
}
void FluidSystem::SPH_DrawDomain ()
{
Vector3DF min, max;
min = m_Vec[SPH_VOLMIN];
max = m_Vec[SPH_VOLMAX];
min.z += 0.5;
glColor3f ( 0.0, 0.0, 1.0 );
glBegin ( GL_LINES );
glVertex3f ( min.x, min.y, min.z ); glVertex3f ( max.x, min.y, min.z );
glVertex3f ( min.x, max.y, min.z ); glVertex3f ( max.x, max.y, min.z );
glVertex3f ( min.x, min.y, min.z ); glVertex3f ( min.x, max.y, min.z );
glVertex3f ( max.x, min.y, min.z ); glVertex3f ( max.x, max.y, min.z );
glEnd ();
}
void FluidSystem::Advance ()
{
char *dat1, *dat1_end;
Fluid* p;
Vector3DF norm, z;
Vector3DF dir, accel;
Vector3DF vnext;
Vector3DF min, max;
double adj;
float SL, SL2, ss, radius;
float stiff, damp, speed, diff;
SL = m_Param[SPH_LIMIT];
SL2 = SL*SL;
stiff = m_Param[SPH_EXTSTIFF];
damp = m_Param[SPH_EXTDAMP];
radius = m_Param[SPH_PRADIUS];
min = m_Vec[SPH_VOLMIN];
max = m_Vec[SPH_VOLMAX];
ss = m_Param[SPH_SIMSCALE];
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
p = (Fluid*) dat1;
// Compute Acceleration
accel = p->sph_force;
accel *= m_Param[SPH_PMASS];
// Velocity limiting
speed = accel.x*accel.x + accel.y*accel.y + accel.z*accel.z;
if ( speed > SL2 ) {
accel *= SL / sqrt(speed);
}
// Boundary Conditions
// Z-axis walls
diff = 2 * radius - ( p->pos.z - min.z - (p->pos.x - m_Vec[SPH_VOLMIN].x) * m_Param[BOUND_ZMIN_SLOPE] )*ss;
if (diff > EPSILON ) {
norm.Set ( -m_Param[BOUND_ZMIN_SLOPE], 0, 1.0 - m_Param[BOUND_ZMIN_SLOPE] );
adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
diff = 2 * radius - ( max.z - p->pos.z )*ss;
if (diff > EPSILON) {
norm.Set ( 0, 0, -1 );
adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
// X-axis walls
if ( !m_Toggle[WRAP_X] ) {
diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1+(p->pos.y*0.025)*0.25) * m_Param[FORCE_XMIN_SIN] )*ss;
//diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMIN_SIN] )*ss;
if (diff > EPSILON ) {
norm.Set ( 1.0, 0, 0 );
adj = (m_Param[ FORCE_XMIN_SIN ] + 1) * stiff * diff - damp * norm.Dot ( p->vel_eval ) ;
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
diff = 2 * radius - ( max.x - p->pos.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMAX_SIN] )*ss;
if (diff > EPSILON) {
norm.Set ( -1, 0, 0 );
adj = (m_Param[ FORCE_XMAX_SIN ]+1) * stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
}
// Y-axis walls
diff = 2 * radius - ( p->pos.y - min.y )*ss;
if (diff > EPSILON) {
norm.Set ( 0, 1, 0 );
adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
diff = 2 * radius - ( max.y - p->pos.y )*ss;
if (diff > EPSILON) {
norm.Set ( 0, -1, 0 );
adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
// Wall barrier
if ( m_Toggle[WALL_BARRIER] ) {
diff = 2 * radius - ( p->pos.x - 0 )*ss;
if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) < 3 && p->pos.z < 10) {
norm.Set ( 1.0, 0, 0 );
adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ;
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
}
// Levy barrier
if ( m_Toggle[LEVY_BARRIER] ) {
diff = 2 * radius - ( p->pos.x - 0 )*ss;
if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) > 5 && p->pos.z < 10) {
norm.Set ( 1.0, 0, 0 );
adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ;
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
}
// Drain barrier
if ( m_Toggle[DRAIN_BARRIER] ) {
diff = 2 * radius - ( p->pos.z - min.z-15 )*ss;
if (diff < 2*radius && diff > EPSILON && (fabs(p->pos.x)>3 || fabs(p->pos.y)>3) ) {
norm.Set ( 0, 0, 1);
adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}
}
// Plane gravity
if ( m_Param[PLANE_GRAV] > 0)
accel += m_Vec[PLANE_GRAV_DIR];
// Point gravity
if ( m_Param[POINT_GRAV] > 0 ) {
norm.x = ( p->pos.x - m_Vec[POINT_GRAV_POS].x );
norm.y = ( p->pos.y - m_Vec[POINT_GRAV_POS].y );
norm.z = ( p->pos.z - m_Vec[POINT_GRAV_POS].z );
norm.Normalize ();
norm *= m_Param[POINT_GRAV];
accel -= norm;
}
// Leapfrog Integration ----------------------------
vnext = accel;
vnext *= m_DT;
vnext += p->vel; // v(t+1/2) = v(t-1/2) + a(t) dt
p->vel_eval = p->vel;
p->vel_eval += vnext;
p->vel_eval *= 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
p->vel = vnext;
vnext *= m_DT/ss;
p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt
if ( m_Param[CLR_MODE]==1.0 ) {
adj = fabs(vnext.x)+fabs(vnext.y)+fabs(vnext.z) / 7000.0;
adj = (adj > 1.0) ? 1.0 : adj;
p->clr = COLORA( 0, adj, adj, 1 );
}
if ( m_Param[CLR_MODE]==2.0 ) {
float v = 0.5 + ( p->pressure / 1500.0);
if ( v < 0.1 ) v = 0.1;
if ( v > 1.0 ) v = 1.0;
p->clr = COLORA ( v, 1-v, 0, 1 );
}
// Euler integration -------------------------------
/* accel += m_Gravity;
accel *= m_DT;
p->vel += accel; // v(t+1) = v(t) + a(t) dt
p->vel_eval += accel;
p->vel_eval *= m_DT/d;
p->pos += p->vel_eval;
p->vel_eval = p->vel; */
if ( m_Toggle[WRAP_X] ) {
diff = p->pos.x - (m_Vec[SPH_VOLMIN].x + 2); // -- Simulates object in center of flow
if ( diff <= 0 ) {
p->pos.x = (m_Vec[SPH_VOLMAX].x - 2) + diff*2;
p->pos.z = 10;
}
}
}
m_Time += m_DT;
}
//------------------------------------------------------ SPH Setup
//
// Range = +/- 10.0 * 0.006 (r) = 0.12 m (= 120 mm = 4.7 inch)
// Container Volume (Vc) = 0.001728 m^3
// Rest Density (D) = 1000.0 kg / m^3
// Particle Mass (Pm) = 0.00020543 kg (mass = vol * density)
// Number of Particles (N) = 4000.0
// Water Mass (M) = 0.821 kg (= 821 grams)
// Water Volume (V) = 0.000821 m^3 (= 3.4 cups, .21 gals)
// Smoothing Radius (R) = 0.02 m (= 20 mm = ~3/4 inch)
// Particle Radius (Pr) = 0.00366 m (= 4 mm = ~1/8 inch)
// Particle Volume (Pv) = 2.054e-7 m^3 (= .268 milliliters)
// Rest Distance (Pd) = 0.0059 m
//
// Given: D, Pm, N
// Pv = Pm / D 0.00020543 kg / 1000 kg/m^3 = 2.054e-7 m^3
// Pv = 4/3*pi*Pr^3 cuberoot( 2.054e-7 m^3 * 3/(4pi) ) = 0.00366 m
// M = Pm * N 0.00020543 kg * 4000.0 = 0.821 kg
// V = M / D 0.821 kg / 1000 kg/m^3 = 0.000821 m^3
// V = Pv * N 2.054e-7 m^3 * 4000 = 0.000821 m^3
// Pd = cuberoot(Pm/D) cuberoot(0.00020543/1000) = 0.0059 m
//
// Ideal grid cell size (gs) = 2 * smoothing radius = 0.02*2 = 0.04
// Ideal domain size = k*gs/d = k*0.02*2/0.005 = k*8 = {8, 16, 24, 32, 40, 48, ..}
// (k = number of cells, gs = cell size, d = simulation scale)
void FluidSystem::SPH_Setup ()
{
m_Param [ SPH_SIMSCALE ] = 0.004; // unit size
m_Param [ SPH_VISC ] = 0.2; // pascal-second (Pa.s) = 1 kg m^-1 s^-1 (see wikipedia page on viscosity)
m_Param [ SPH_RESTDENSITY ] = 600.0; // kg / m^3
m_Param [ SPH_PMASS ] = 0.00020543; // kg
m_Param [ SPH_PRADIUS ] = 0.004; // m
m_Param [ SPH_PDIST ] = 0.0059; // m
m_Param [ SPH_SMOOTHRADIUS ] = 0.01; // m
m_Param [ SPH_INTSTIFF ] = 1.00;
m_Param [ SPH_EXTSTIFF ] = 10000.0;
m_Param [ SPH_EXTDAMP ] = 256.0;
m_Param [ SPH_LIMIT ] = 200.0; // m / s
m_Toggle [ SPH_GRID ] = false;
m_Toggle [ SPH_DEBUG ] = false;
SPH_ComputeKernels ();
}
void FluidSystem::SPH_ComputeKernels ()
{
m_Param [ SPH_PDIST ] = pow ( m_Param[SPH_PMASS] / m_Param[SPH_RESTDENSITY], 1/3.0 );
m_R2 = m_Param [SPH_SMOOTHRADIUS] * m_Param[SPH_SMOOTHRADIUS];
m_Poly6Kern = 315.0f / (64.0f * 3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 9) ); // Wpoly6 kernel (denominator part) - 2003 Muller, p.4
m_SpikyKern = -45.0f / (3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 6) ); // Laplacian of viscocity (denominator): PI h^6
m_LapKern = 45.0f / (3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 6) );
}
void FluidSystem::SPH_CreateExample ( int n, int nmax )
{
Vector3DF pos;
Vector3DF min, max;
Reset ( nmax );
switch ( n ) {
case 0: // Wave pool
//-- TEST CASE: 2x2x2 grid, 32 particles. NOTE: Set PRADIUS to 0.0004 to reduce wall influence
// grid 0: 3*3*2 = 18 particles
// grid 1,2: 3*1*2 = 6 particles
// grid 3: 1*1*2 = 2 particles
// grid 4,5,6: 0 = 0 particles
/*m_Vec [ SPH_VOLMIN ].Set ( -2.5, -2.5, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 2.5, 2.5, 5.0 );
m_Vec [ SPH_INITMIN ].Set ( -2.5, -2.5, 0 );
m_Vec [ SPH_INITMAX ].Set ( 2.5, 2.5, 1.6 );*/
m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 40 );
//m_Vec [ SPH_INITMIN ].Set ( -5, -5, 10 );
//m_Vec [ SPH_INITMAX ].Set ( 5, 5, 20 );
m_Vec [ SPH_INITMIN ].Set ( -20, -26, 10 );
m_Vec [ SPH_INITMAX ].Set ( 20, 26, 40 );
m_Param [ FORCE_XMIN_SIN ] = 12.0;
m_Param [ BOUND_ZMIN_SLOPE ] = 0.05;
break;
case 1: // Dam break
m_Vec [ SPH_VOLMIN ].Set ( -30, -14, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 30, 14, 60 );
m_Vec [ SPH_INITMIN ].Set ( 0, -13, 0 );
m_Vec [ SPH_INITMAX ].Set ( 29, 13, 30 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 2: // Dual-Wave pool
m_Vec [ SPH_VOLMIN ].Set ( -60, -5, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 60, 5, 50 );
m_Vec [ SPH_INITMIN ].Set ( -46, -5, 0 );
m_Vec [ SPH_INITMAX ].Set ( 46, 5, 15 );
m_Param [ FORCE_XMIN_SIN ] = 8.0;
m_Param [ FORCE_XMAX_SIN ] = 8.0;
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 3: // Swirl Stream
m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 50 );
m_Vec [ SPH_INITMIN ].Set ( -30, -30, 0 );
m_Vec [ SPH_INITMAX ].Set ( 30, 30, 40 );
m_Vec [ EMIT_POS ].Set ( -20, -20, 22 );
m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 );
m_Vec [ EMIT_ANG ].Set ( 0, 120, 1.5 );
m_Vec [ EMIT_DANG ].Set ( 0, 0, 0 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 4: // Shockwave
m_Vec [ SPH_VOLMIN ].Set ( -60, -15, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 60, 15, 50 );
m_Vec [ SPH_INITMIN ].Set ( -59, -14, 0 );
m_Vec [ SPH_INITMAX ].Set ( 59, 14, 30 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
m_Toggle [ WALL_BARRIER ] = true;
m_Toggle [ WRAP_X ] = true;
break;
case 5: // Zero gravity
m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 );
m_Vec [ SPH_INITMIN ].Set ( -20, -20, 20 );
m_Vec [ SPH_INITMAX ].Set ( 20, 20, 40 );
m_Vec [ EMIT_POS ].Set ( -20, 0, 40 );
m_Vec [ EMIT_RATE ].Set ( 2, 1, 0 );
m_Vec [ EMIT_ANG ].Set ( 0, 120, 0.25 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, 0 );
m_Param [ SPH_INTSTIFF ] = 0.20;
break;
case 6: // Point gravity
m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 );
m_Vec [ SPH_INITMIN ].Set ( -20, -20, 20 );
m_Vec [ SPH_INITMAX ].Set ( 20, 20, 40 );
m_Param [ SPH_INTSTIFF ] = 0.50;
m_Vec [ EMIT_POS ].Set ( -20, 20, 25 );
m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 );
m_Vec [ EMIT_ANG ].Set ( -20, 100, 2.0 );
m_Vec [ POINT_GRAV_POS ].Set ( 0, 0, 25 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, 0 );
m_Param [ POINT_GRAV ] = 3.5;
break;
case 7: // Levy break
m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 );
m_Vec [ SPH_INITMIN ].Set ( 10, -40, 0 );
m_Vec [ SPH_INITMAX ].Set ( 40, 40, 50 );
m_Vec [ EMIT_POS ].Set ( 34, 27, 16.6 );
m_Vec [ EMIT_RATE ].Set ( 2, 9, 0 );
m_Vec [ EMIT_ANG ].Set ( 118, 200, 1.0 );
m_Toggle [ LEVY_BARRIER ] = true;
m_Param [ BOUND_ZMIN_SLOPE ] = 0.1;
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 8: // Drain
m_Vec [ SPH_VOLMIN ].Set ( -20, -20, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 20, 20, 50 );
m_Vec [ SPH_INITMIN ].Set ( -15, -20, 20 );
m_Vec [ SPH_INITMAX ].Set ( 20, 20, 50 );
m_Vec [ EMIT_POS ].Set ( -16, -16, 30 );
m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 );
m_Vec [ EMIT_ANG ].Set ( -20, 140, 1.8 );
m_Toggle [ DRAIN_BARRIER ] = true;
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 9: // Tumbler
m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 50 );
m_Vec [ SPH_INITMIN ].Set ( 24, -29, 20 );
m_Vec [ SPH_INITMAX ].Set ( 29, 29, 40 );
m_Param [ SPH_VISC ] = 0.1;
m_Param [ SPH_INTSTIFF ] = 0.50;
m_Param [ SPH_EXTSTIFF ] = 8000;
//m_Param [ SPH_SMOOTHRADIUS ] = 0.01;
m_Param [ BOUND_ZMIN_SLOPE ] = 0.4;
m_Param [ FORCE_XMIN_SIN ] = 12.00;
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
case 10: // Large sim
m_Vec [ SPH_VOLMIN ].Set ( -35, -35, 0 );
m_Vec [ SPH_VOLMAX ].Set ( 35, 35, 60 );
m_Vec [ SPH_INITMIN ].Set ( -5, -35, 0 );
m_Vec [ SPH_INITMAX ].Set ( 30, 0, 60 );
m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 );
break;
}
SPH_ComputeKernels ();
m_Param [ SPH_SIMSIZE ] = m_Param [ SPH_SIMSCALE ] * (m_Vec[SPH_VOLMAX].z - m_Vec[SPH_VOLMIN].z);
m_Param [ SPH_PDIST ] = pow ( m_Param[SPH_PMASS] / m_Param[SPH_RESTDENSITY], 1/3.0 );
float ss = m_Param [ SPH_PDIST ]*0.87 / m_Param[ SPH_SIMSCALE ];
printf ( "Spacing: %f\n", ss);
AddVolume ( m_Vec[SPH_INITMIN], m_Vec[SPH_INITMAX], ss ); // Create the particles
float cell_size = m_Param[SPH_SMOOTHRADIUS]*2.0; // Grid cell size (2r)
Grid_Setup ( m_Vec[SPH_VOLMIN], m_Vec[SPH_VOLMAX], m_Param[SPH_SIMSCALE], cell_size, 1.0 ); // Setup grid
Grid_InsertParticles (); // Insert particles
Vector3DF vmin, vmax;
vmin = m_Vec[SPH_VOLMIN];
vmin -= Vector3DF(2,2,2);
vmax = m_Vec[SPH_VOLMAX];
vmax += Vector3DF(2,2,-2);
#ifdef BUILD_CUDA
FluidClearCUDA ();
Sleep ( 500 );
FluidSetupCUDA ( NumPoints(), sizeof(Fluid), *(float3*)& m_GridMin, *(float3*)& m_GridMax, *(float3*)& m_GridRes, *(float3*)& m_GridSize, (int) m_Vec[EMIT_RATE].x );
Sleep ( 500 );
FluidParamCUDA ( m_Param[SPH_SIMSCALE], m_Param[SPH_SMOOTHRADIUS], m_Param[SPH_PMASS], m_Param[SPH_RESTDENSITY], m_Param[SPH_INTSTIFF], m_Param[SPH_VISC] );
#endif
}
// Compute Pressures - Very slow yet simple. O(n^2)
void FluidSystem::SPH_ComputePressureSlow ()
{
char *dat1, *dat1_end;
char *dat2, *dat2_end;
Fluid *p, *q;
int cnt = 0;
double dx, dy, dz, sum, dsq, c;
double d, d2, mR, mR2;
d = m_Param[SPH_SIMSCALE];
d2 = d*d;
mR = m_Param[SPH_SMOOTHRADIUS];
mR2 = mR*mR;
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
p = (Fluid*) dat1;
sum = 0.0;
cnt = 0;
dat2_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat2 = mBuf[0].data; dat2 < dat2_end; dat2 += mBuf[0].stride ) {
q = (Fluid*) dat2;
if ( p==q ) continue;
dx = ( p->pos.x - q->pos.x)*d; // dist in cm
dy = ( p->pos.y - q->pos.y)*d;
dz = ( p->pos.z - q->pos.z)*d;
dsq = (dx*dx + dy*dy + dz*dz);
if ( mR2 > dsq ) {
c = m_R2 - dsq;
sum += c * c * c;
cnt++;
//if ( p == m_CurrP ) q->tag = true;
}
}
p->density = sum * m_Param[SPH_PMASS] * m_Poly6Kern ;
p->pressure = ( p->density - m_Param[SPH_RESTDENSITY] ) * m_Param[SPH_INTSTIFF];
p->density = 1.0f / p->density;
}
}
// Compute Pressures - Using spatial grid, and also create neighbor table
void FluidSystem::SPH_ComputePressureGrid ()
{
char *dat1, *dat1_end;
Fluid* p;
Fluid* pcurr;
int pndx;
int i, cnt = 0;
float dx, dy, dz, sum, dsq, c;
float d, d2, mR, mR2;
float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE];
d = m_Param[SPH_SIMSCALE];
d2 = d*d;
mR = m_Param[SPH_SMOOTHRADIUS];
mR2 = mR*mR;
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
i = 0;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride, i++ ) {
p = (Fluid*) dat1;
sum = 0.0;
m_NC[i] = 0;
Grid_FindCells ( p->pos, radius );
for (int cell=0; cell < 8; cell++) {
if ( m_GridCell[cell] != -1 ) {
pndx = m_Grid [ m_GridCell[cell] ];
while ( pndx != -1 ) {
pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride);
if ( pcurr == p ) {pndx = pcurr->next; continue; }
dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm
dy = ( p->pos.y - pcurr->pos.y)*d;
dz = ( p->pos.z - pcurr->pos.z)*d;
dsq = (dx*dx + dy*dy + dz*dz);
if ( mR2 > dsq ) {
c = m_R2 - dsq;
sum += c * c * c;
if ( m_NC[i] < MAX_NEIGHBOR ) {
m_Neighbor[i][ m_NC[i] ] = pndx;
m_NDist[i][ m_NC[i] ] = sqrt(dsq);
m_NC[i]++;
}
}
pndx = pcurr->next;
}
}
m_GridCell[cell] = -1;
}
p->density = sum * m_Param[SPH_PMASS] * m_Poly6Kern ;
p->pressure = ( p->density - m_Param[SPH_RESTDENSITY] ) * m_Param[SPH_INTSTIFF];
p->density = 1.0f / p->density;
}
}
// Compute Forces - Very slow, but simple. O(n^2)
void FluidSystem::SPH_ComputeForceSlow ()
{
char *dat1, *dat1_end;
char *dat2, *dat2_end;
Fluid *p, *q;
Vector3DF force, fcurr;
register double pterm, vterm, dterm;
double c, r, d, sum, dsq;
double dx, dy, dz;
double mR, mR2, visc;
d = m_Param[SPH_SIMSCALE];
mR = m_Param[SPH_SMOOTHRADIUS];
mR2 = (mR*mR);
visc = m_Param[SPH_VISC];
vterm = m_LapKern * visc;
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
p = (Fluid*) dat1;
sum = 0.0;
force.Set ( 0, 0, 0 );
dat2_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat2 = mBuf[0].data; dat2 < dat2_end; dat2 += mBuf[0].stride ) {
q = (Fluid*) dat2;
if ( p == q ) continue;
dx = ( p->pos.x - q->pos.x )*d; // dist in cm
dy = ( p->pos.y - q->pos.y )*d;
dz = ( p->pos.z - q->pos.z )*d;
dsq = (dx*dx + dy*dy + dz*dz);
if ( mR2 > dsq ) {
r = sqrt ( dsq );
c = (mR - r);
pterm = -0.5f * c * m_SpikyKern * ( p->pressure + q->pressure) / r;
dterm = c * p->density * q->density;
force.x += ( pterm * dx + vterm * (q->vel_eval.x - p->vel_eval.x) ) * dterm;
force.y += ( pterm * dy + vterm * (q->vel_eval.y - p->vel_eval.y) ) * dterm;
force.z += ( pterm * dz + vterm * (q->vel_eval.z - p->vel_eval.z) ) * dterm;
}
}
p->sph_force = force;
}
}
// Compute Forces - Using spatial grid. Faster.
void FluidSystem::SPH_ComputeForceGrid ()
{
char *dat1, *dat1_end;
Fluid *p;
Fluid *pcurr;
int pndx;
Vector3DF force, fcurr;
register double pterm, vterm, dterm;
double c, d, dsq, r;
double dx, dy, dz;
double mR, mR2, visc;
float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE];
d = m_Param[SPH_SIMSCALE];
mR = m_Param[SPH_SMOOTHRADIUS];
mR2 = (mR*mR);
visc = m_Param[SPH_VISC];
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
p = (Fluid*) dat1;
force.Set ( 0, 0, 0 );
Grid_FindCells ( p->pos, radius );
for (int cell=0; cell < 8; cell++) {
if ( m_GridCell[cell] != -1 ) {
pndx = m_Grid [ m_GridCell[cell] ];
while ( pndx != -1 ) {
pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride);
if ( pcurr == p ) {pndx = pcurr->next; continue; }
dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm
dy = ( p->pos.y - pcurr->pos.y)*d;
dz = ( p->pos.z - pcurr->pos.z)*d;
dsq = (dx*dx + dy*dy + dz*dz);
if ( mR2 > dsq ) {
r = sqrt ( dsq );
c = (mR - r);
pterm = -0.5f * c * m_SpikyKern * ( p->pressure + pcurr->pressure) / r;
dterm = c * p->density * pcurr->density;
vterm = m_LapKern * visc;
force.x += ( pterm * dx + vterm * (pcurr->vel_eval.x - p->vel_eval.x) ) * dterm;
force.y += ( pterm * dy + vterm * (pcurr->vel_eval.y - p->vel_eval.y) ) * dterm;
force.z += ( pterm * dz + vterm * (pcurr->vel_eval.z - p->vel_eval.z) ) * dterm;
}
pndx = pcurr->next;
}
}
}
p->sph_force = force;
}
}
// Compute Forces - Using spatial grid with saved neighbor table. Fastest.
void FluidSystem::SPH_ComputeForceGridNC ()
{
char *dat1, *dat1_end;
Fluid *p;
Fluid *pcurr;
Vector3DF force, fcurr;
register float pterm, vterm, dterm;
int i;
float c, d;
float dx, dy, dz;
float mR, mR2, visc;
d = m_Param[SPH_SIMSCALE];
mR = m_Param[SPH_SMOOTHRADIUS];
mR2 = (mR*mR);
visc = m_Param[SPH_VISC];
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
i = 0;
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride, i++ ) {
p = (Fluid*) dat1;
force.Set ( 0, 0, 0 );
for (int j=0; j < m_NC[i]; j++ ) {
pcurr = (Fluid*) (mBuf[0].data + m_Neighbor[i][j]*mBuf[0].stride);
dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm
dy = ( p->pos.y - pcurr->pos.y)*d;
dz = ( p->pos.z - pcurr->pos.z)*d;
c = ( mR - m_NDist[i][j] );
pterm = -0.5f * c * m_SpikyKern * ( p->pressure + pcurr->pressure) / m_NDist[i][j];
dterm = c * p->density * pcurr->density;
vterm = m_LapKern * visc;
force.x += ( pterm * dx + vterm * (pcurr->vel_eval.x - p->vel_eval.x) ) * dterm;
force.y += ( pterm * dy + vterm * (pcurr->vel_eval.y - p->vel_eval.y) ) * dterm;
force.z += ( pterm * dz + vterm * (pcurr->vel_eval.z - p->vel_eval.z) ) * dterm;
}
p->sph_force = force;
}
}

View File

@@ -0,0 +1,71 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <cutil.h>
#include <cstdlib>
#include <cstdio>
#include <string.h>
#if defined(__APPLE__) || defined(MACOSX)
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <cuda_gl_interop.h>
#include "fluid_system_kern.cu"
extern "C"
{
// Compute number of blocks to create
int iDivUp (int a, int b) {
return (a % b != 0) ? (a / b + 1) : (a / b);
}
void computeNumBlocks (int numPnts, int minThreads, int &numBlocks, int &numThreads)
{
numThreads = min( minThreads, numPnts );
numBlocks = iDivUp ( numPnts, numThreads );
}
void Grid_InsertParticlesCUDA ( uchar* data, uint stride, uint numPoints )
{
int numThreads, numBlocks;
computeNumBlocks (numPoints, 256, numBlocks, numThreads);
// transfer point data to device
char* pntData;
size = numPoints * stride;
cudaMalloc( (void**) &pntData, size);
cudaMemcpy( pntData, data, size, cudaMemcpyHostToDevice);
// execute the kernel
insertParticles<<< numBlocks, numThreads >>> ( pntData, stride );
// transfer data back to host
cudaMemcpy( data, pntData, cudaMemcpyDeviceToHost);
// check if kernel invocation generated an error
CUT_CHECK_ERROR("Kernel execution failed");
CUDA_SAFE_CALL(cudaGLUnmapBufferObject(vboPos));
}

View File

@@ -0,0 +1,106 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEF_FLUID_SYS
#define DEF_FLUID_SYS
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "point_set.h"
#include "fluid.h"
// Scalar params
#define SPH_SIMSIZE 4
#define SPH_SIMSCALE 5
#define SPH_VISC 6
#define SPH_RESTDENSITY 7
#define SPH_PMASS 8
#define SPH_PRADIUS 9
#define SPH_PDIST 10
#define SPH_SMOOTHRADIUS 11
#define SPH_INTSTIFF 12
#define SPH_EXTSTIFF 13
#define SPH_EXTDAMP 14
#define SPH_LIMIT 15
#define BOUND_ZMIN_SLOPE 16
#define FORCE_XMAX_SIN 17
#define FORCE_XMIN_SIN 18
#define MAX_FRAC 19
#define CLR_MODE 20
// Vector params
#define SPH_VOLMIN 7
#define SPH_VOLMAX 8
#define SPH_INITMIN 9
#define SPH_INITMAX 10
// Toggles
#define SPH_GRID 0
#define SPH_DEBUG 1
#define WRAP_X 2
#define WALL_BARRIER 3
#define LEVY_BARRIER 4
#define DRAIN_BARRIER 5
#define USE_CUDA 6
#define MAX_PARAM 21
#define BFLUID 2
class FluidSystem : public PointSet {
public:
FluidSystem ();
// Basic Particle System
virtual void Initialize ( int mode, int nmax );
virtual void Reset ( int nmax );
virtual void Run ();
virtual void Advance ();
virtual int AddPoint ();
virtual int AddPointReuse ();
Fluid* AddFluid () { return (Fluid*) GetElem(0, AddPointReuse()); }
Fluid* GetFluid (int n) { return (Fluid*) GetElem(0, n); }
// Smoothed Particle Hydrodynamics
void SPH_Setup ();
void SPH_CreateExample ( int n, int nmax );
void SPH_DrawDomain ();
void SPH_ComputeKernels ();
void SPH_ComputePressureSlow (); // O(n^2)
void SPH_ComputePressureGrid (); // O(kn) - spatial grid
void SPH_ComputeForceSlow (); // O(n^2)
void SPH_ComputeForceGrid (); // O(kn) - spatial grid
void SPH_ComputeForceGridNC (); // O(cn) - neighbor table
private:
// Smoothed Particle Hydrodynamics
double m_R2, m_Poly6Kern, m_LapKern, m_SpikyKern; // Kernel functions
};
#endif

View File

@@ -0,0 +1,247 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "C:\CUDA\common\inc\cutil.h" // cutil32.lib
#include <string.h>
#if defined(__APPLE__) || defined(MACOSX)
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <cuda_gl_interop.h>
#include "radixsort.cu"
#include "fluid_system_kern.cu" // build kernel
FluidParams fcuda;
__device__ char* bufPnts; // point data (array of Fluid structs)
__device__ char* bufPntSort; // point data (array of Fluid structs)
__device__ uint* bufHash[2]; // point grid hash
__device__ int* bufGrid;
extern "C"
{
// Initialize CUDA
void cudaInit(int argc, char **argv)
{
CUT_DEVICE_INIT(argc, argv);
cudaDeviceProp p;
cudaGetDeviceProperties ( &p, 0);
printf ( "-- CUDA --\n" );
printf ( "Name: %s\n", p.name );
printf ( "Revision: %d.%d\n", p.major, p.minor );
printf ( "Global Mem: %d\n", p.totalGlobalMem );
printf ( "Shared/Blk: %d\n", p.sharedMemPerBlock );
printf ( "Regs/Blk: %d\n", p.regsPerBlock );
printf ( "Warp Size: %d\n", p.warpSize );
printf ( "Mem Pitch: %d\n", p.memPitch );
printf ( "Thrds/Blk: %d\n", p.maxThreadsPerBlock );
printf ( "Const Mem: %d\n", p.totalConstMem );
printf ( "Clock Rate: %d\n", p.clockRate );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufPnts, 10 ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufPntSort, 10 ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufHash, 10 ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufGrid, 10 ) );
};
// Compute number of blocks to create
int iDivUp (int a, int b) {
return (a % b != 0) ? (a / b + 1) : (a / b);
}
void computeNumBlocks (int numPnts, int maxThreads, int &numBlocks, int &numThreads)
{
numThreads = min( maxThreads, numPnts );
numBlocks = iDivUp ( numPnts, numThreads );
}
void FluidClearCUDA ()
{
CUDA_SAFE_CALL ( cudaFree ( bufPnts ) );
CUDA_SAFE_CALL ( cudaFree ( bufPntSort ) );
CUDA_SAFE_CALL ( cudaFree ( bufHash[0] ) );
CUDA_SAFE_CALL ( cudaFree ( bufHash[1] ) );
CUDA_SAFE_CALL ( cudaFree ( bufGrid ) );
}
void FluidSetupCUDA ( int num, int stride, float3 min, float3 max, float3 res, float3 size, int chk )
{
fcuda.min = make_float3(min.x, min.y, min.z);
fcuda.max = make_float3(max.x, max.y, max.z);
fcuda.res = make_float3(res.x, res.y, res.z);
fcuda.size = make_float3(size.x, size.y, size.z);
fcuda.pnts = num;
fcuda.delta.x = res.x / size.x;
fcuda.delta.y = res.y / size.y;
fcuda.delta.z = res.z / size.z;
fcuda.cells = res.x*res.y*res.z;
fcuda.chk = chk;
computeNumBlocks ( fcuda.pnts, 256, fcuda.numBlocks, fcuda.numThreads); // particles
computeNumBlocks ( fcuda.cells, 256, fcuda.gridBlocks, fcuda.gridThreads); // grid cell
fcuda.szPnts = (fcuda.numBlocks * fcuda.numThreads) * stride;
fcuda.szHash = (fcuda.numBlocks * fcuda.numThreads) * sizeof(uint2); // <cell, particle> pairs
fcuda.szGrid = (fcuda.gridBlocks * fcuda.gridThreads) * sizeof(uint);
fcuda.stride = stride;
printf ( "pnts: %d, t:%dx%d=%d, bufPnts:%d, bufHash:%d\n", fcuda.pnts, fcuda.numBlocks, fcuda.numThreads, fcuda.numBlocks*fcuda.numThreads, fcuda.szPnts, fcuda.szHash );
printf ( "grds: %d, t:%dx%d=%d, bufGrid:%d, Res: %dx%dx%d\n", fcuda.cells, fcuda.gridBlocks, fcuda.gridThreads, fcuda.gridBlocks*fcuda.gridThreads, fcuda.szGrid, (int) fcuda.res.x, (int) fcuda.res.y, (int) fcuda.res.z );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufPnts, fcuda.szPnts ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufPntSort, fcuda.szPnts ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufHash[0], fcuda.szHash ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufHash[1], fcuda.szHash ) );
CUDA_SAFE_CALL ( cudaMalloc ( (void**) &bufGrid, fcuda.szGrid ) );
printf ( "POINTERS\n");
printf ( "bufPnts: %p\n", bufPnts );
printf ( "bufPntSort: %p\n", bufPntSort );
printf ( "bufHash0: %p\n", bufHash[0] );
printf ( "bufHash1: %p\n", bufHash[1] );
printf ( "bufGrid: %p\n", bufGrid );
CUDA_SAFE_CALL ( cudaMemcpyToSymbol ( simData, &fcuda, sizeof(FluidParams) ) );
cudaThreadSynchronize ();
}
void FluidParamCUDA ( float sim_scale, float smooth_rad, float mass, float rest, float stiff, float visc )
{
fcuda.sim_scale = sim_scale;
fcuda.smooth_rad = smooth_rad;
fcuda.r2 = smooth_rad * smooth_rad;
fcuda.pmass = mass;
fcuda.rest_dens = rest;
fcuda.stiffness = stiff;
fcuda.visc = visc;
fcuda.pdist = pow ( fcuda.pmass / fcuda.rest_dens, 1/3.0f );
fcuda.poly6kern = 315.0f / (64.0f * 3.141592 * pow( smooth_rad, 9.0f) );
fcuda.spikykern = -45.0f / (3.141592 * pow( smooth_rad, 6.0f) );
fcuda.lapkern = 45.0f / (3.141592 * pow( smooth_rad, 6.0f) );
CUDA_SAFE_CALL( cudaMemcpyToSymbol ( simData, &fcuda, sizeof(FluidParams) ) );
cudaThreadSynchronize ();
}
void TransferToCUDA ( char* data, int* grid, int numPoints )
{
CUDA_SAFE_CALL( cudaMemcpy ( bufPnts, data, numPoints * fcuda.stride, cudaMemcpyHostToDevice ) );
cudaThreadSynchronize ();
}
void TransferFromCUDA ( char* data, int* grid, int numPoints )
{
CUDA_SAFE_CALL( cudaMemcpy ( data, bufPntSort, numPoints * fcuda.stride, cudaMemcpyDeviceToHost ) );
cudaThreadSynchronize ();
CUDA_SAFE_CALL( cudaMemcpy ( grid, bufGrid, fcuda.cells * sizeof(uint), cudaMemcpyDeviceToHost ) );
}
void Grid_InsertParticlesCUDA ()
{
CUDA_SAFE_CALL( cudaMemset ( bufHash[0], 0, fcuda.szHash ) );
hashParticles<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPnts, (uint2*) bufHash[0], fcuda.pnts );
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
//int buf[20000];
/*printf ( "HASH: %d (%d)\n", fcuda.pnts, fcuda.numBlocks*fcuda.numThreads );
CUDA_SAFE_CALL( cudaMemcpy ( buf, bufHash[0], fcuda.pnts * 2*sizeof(uint), cudaMemcpyDeviceToHost ) );
//for (int n=0; n < fcuda.numBlocks*fcuda.numThreads; n++) {
for (int n=0; n < 100; n++) {
printf ( "%d: <%d,%d>\n", n, buf[n*2], buf[n*2+1] );
}*/
RadixSort( (KeyValuePair *) bufHash[0], (KeyValuePair *) bufHash[1], fcuda.pnts, 32);
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
/*printf ( "HASH: %d (%d)\n", fcuda.pnts, fcuda.numBlocks*fcuda.numThreads );
CUDA_SAFE_CALL( cudaMemcpy ( buf, bufHash[0], fcuda.pnts * 2*sizeof(uint), cudaMemcpyDeviceToHost ) );
//for (int n=0; n < fcuda.numBlocks*fcuda.numThreads; n++) {
for (int n=0; n < 100; n++) {
printf ( "%d: <%d,%d>\n", n, buf[n*2], buf[n*2+1] );
}*/
// insertParticles<<< fcuda.gridBlocks, fcuda.gridThreads>>> ( bufPnts, (uint2*) bufHash[0], bufGrid, fcuda.pnts, fcuda.cells );
CUDA_SAFE_CALL( cudaMemset ( bufGrid, NULL_HASH, fcuda.cells * sizeof(uint) ) );
insertParticlesRadix<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPnts, (uint2*) bufHash[0], bufGrid, bufPntSort, fcuda.pnts, fcuda.cells );
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
/*printf ( "GRID: %d\n", fcuda.cells );
CUDA_SAFE_CALL( cudaMemcpy ( buf, bufGrid, fcuda.cells * sizeof(uint), cudaMemcpyDeviceToHost ) );
*for (int n=0; n < 100; n++) {
printf ( "%d: %d\n", n, buf[n]);
}*/
}
void SPH_ComputePressureCUDA ()
{
computePressure<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, bufGrid, (uint2*) bufHash[0], fcuda.pnts );
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
}
void SPH_ComputeForceCUDA ()
{
//-- standard force
//computeForce<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, bufGrid, (uint2*) bufHash[0], fcuda.pnts );
// Force using neighbor table
computeForceNbr<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, fcuda.pnts );
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
}
void SPH_AdvanceCUDA ( float dt, float ss )
{
advanceParticles<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, fcuda.pnts, dt, ss );
CUT_CHECK_ERROR( "Kernel execution failed");
cudaThreadSynchronize ();
}
} // extern C
//----------- Per frame: Malloc/Free, Host<->Device
// transfer point data to device
/*char* pntData;
int size = (fcuda.numBlocks*fcuda.numThreads) * stride;
cudaMalloc( (void**) &pntData, size);
cudaMemcpy( pntData, data, numPoints*stride, cudaMemcpyHostToDevice);
insertParticles<<< fcuda.numBlocks, fcuda.numThreads >>> ( pntData, stride, numPoints );
cudaMemcpy( data, pntData, numPoints*stride, cudaMemcpyDeviceToHost);
cudaFree( pntData );*/

View File

@@ -0,0 +1,63 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <vector_types.h>
#include <driver_types.h> // for cudaStream_t
typedef unsigned int uint; // should be 4-bytes on CUDA
typedef unsigned char uchar; // should be 1-bytes on CUDA
struct FluidParams {
int numThreads, numBlocks;
int gridThreads, gridBlocks;
int szPnts, szHash, szGrid;
int stride, pnts, cells;
int chk;
float smooth_rad, r2, sim_scale, visc;
float3 min, max, res, size, delta;
float pdist, pmass, rest_dens, stiffness;
float poly6kern, spikykern, lapkern;
};
extern "C"
{
void cudaInit(int argc, char **argv);
void FluidClearCUDA ();
void FluidSetupCUDA ( int num, int stride, float3 min, float3 max, float3 res, float3 size, int chk );
void FluidParamCUDA ( float sim_scale, float smooth_rad, float mass, float rest, float stiff, float visc );
void TransferToCUDA ( char* data, int* grid, int numPoints );
void TransferFromCUDA ( char* data, int* grid, int numPoints );
void Grid_InsertParticlesCUDA ();
void SPH_ComputePressureCUDA ();
void SPH_ComputeForceCUDA ();
void SPH_AdvanceCUDA ( float dt, float ss );
}

View File

@@ -0,0 +1,402 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _PARTICLES_KERNEL_H_
#define _PARTICLES_KERNEL_H_
#include <stdio.h>
#include <math.h>
#include "fluid_system_host.cuh"
#define TOTAL_THREADS 65536
#define BLOCK_THREADS 256
#define MAX_NBR 80
__constant__ FluidParams simData; // simulation data (on device)
__device__ int bufNeighbor[ TOTAL_THREADS*MAX_NBR ];
__device__ float bufNdist[ TOTAL_THREADS*MAX_NBR ];
#define COLOR(r,g,b) ( (uint((r)*255.0f)<<24) | (uint((g)*255.0f)<<16) | (uint((b)*255.0f)<<8) )
#define COLORA(r,g,b,a) ( (uint((r)*255.0f)<<24) | (uint((g)*255.0f)<<16) | (uint((b)*255.0f)<<8) | uint((a)*255.0f) )
#define NULL_HASH 333333
#define OFFSET_CLR 12
#define OFFSET_NEXT 16
#define OFFSET_VEL 20
#define OFFSET_VEVAL 32
#define OFFSET_PRESS 48
#define OFFSET_DENS 52
#define OFFSET_FORCE 56
__global__ void hashParticles ( char* bufPnts, uint2* bufHash, int numPnt )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
float3* pos = (float3*) (bufPnts + __mul24(ndx, simData.stride) );
int gz = (pos->z - simData.min.z) * simData.delta.z ;
int gy = (pos->y - simData.min.y) * simData.delta.y ;
int gx = (pos->x - simData.min.x) * simData.delta.x ;
if ( ndx >= numPnt || gx < 0 || gz > simData.res.x-1 || gy < 0 || gy > simData.res.y-1 || gz < 0 || gz > simData.res.z-1 )
bufHash[ndx] = make_uint2( NULL_HASH, ndx );
else
bufHash[ndx] = make_uint2( __mul24(__mul24(gz, (int) simData.res.y)+gy, (int) simData.res.x) + gx, ndx );
__syncthreads ();
}
__global__ void insertParticles ( char* bufPnts, uint2* bufHash, int* bufGrid, int numPnt, int numGrid )
{
uint grid_ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // grid cell index
bufPnts += OFFSET_NEXT;
bufGrid[grid_ndx] = -1;
for (int n=0; n < numPnt; n++) {
if ( bufHash[n].x == grid_ndx ) {
*(int*) (bufPnts + __mul24(bufHash[n].y, simData.stride)) = bufGrid[grid_ndx];
bufGrid[grid_ndx] = bufHash[n].y;
}
}
__syncthreads ();
}
__global__ void insertParticlesRadix ( char* bufPnts, uint2* bufHash, int* bufGrid, char* bufPntSort, int numPnt, int numGrid )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
uint2 bufHashSort = bufHash[ndx];
__shared__ uint sharedHash[257];
sharedHash[threadIdx.x+1] = bufHashSort.x;
if ( ndx > 0 && threadIdx.x == 0 ) {
volatile uint2 prevData = bufHash[ndx-1];
sharedHash[0] = prevData.x;
}
__syncthreads ();
if ( (ndx == 0 || bufHashSort.x != sharedHash[threadIdx.x]) && bufHashSort.x != NULL_HASH ) {
bufGrid [ bufHashSort.x ] = ndx;
}
if ( ndx < numPnt ) {
char* src = bufPnts + __mul24( bufHashSort.y, simData.stride );
char* dest = bufPntSort + __mul24( ndx, simData.stride );
*(float3*)(dest) = *(float3*)(src);
*(uint*) (dest + OFFSET_CLR) = *(uint*) (src + OFFSET_CLR);
*(float3*)(dest + OFFSET_VEL) = *(float3*)(src + OFFSET_VEL);
*(float3*)(dest + OFFSET_VEVAL) = *(float3*)(src + OFFSET_VEVAL);
*(float*) (dest + OFFSET_DENS) = 0.0;
*(float*) (dest + OFFSET_PRESS) = 0.0;
*(float3*) (dest + OFFSET_FORCE)= make_float3(0,0,0);
*(int*) (dest + OFFSET_NEXT) = bufHashSort.x;
}
__syncthreads ();
}
//__shared__ int ncount [ BLOCK_THREADS ];
__device__ float contributePressure ( int pndx, float3* p, int qndx, int grid_ndx, char* bufPnts, uint2* bufHash )
{
float3* qpos;
float3 dist;
float dsq, c, sum;
float d = simData.sim_scale;
int nbr = __mul24(pndx, MAX_NBR);
sum = 0.0;
for ( ; qndx < simData.pnts; qndx++ ) {
if ( bufHash[qndx].x != grid_ndx || qndx == NULL_HASH) break;
if ( qndx != pndx ) {
qpos = (float3*) ( bufPnts + __mul24(qndx, simData.stride ));
dist.x = ( p->x - qpos->x )*d; // dist in cm
dist.y = ( p->y - qpos->y )*d;
dist.z = ( p->z - qpos->z )*d;
dsq = (dist.x*dist.x + dist.y*dist.y + dist.z*dist.z);
if ( dsq < simData.r2 ) {
c = simData.r2 - dsq;
sum += c * c * c;
if ( bufNeighbor[nbr] < MAX_NBR ) {
bufNeighbor[ nbr+bufNeighbor[nbr] ] = qndx;
bufNdist[ nbr+bufNeighbor[nbr] ] = sqrt(dsq);
bufNeighbor[nbr]++;
}
}
}
//curr = *(int*) (bufPnts + __mul24(curr, simData.stride) + OFFSET_NEXT);
}
return sum;
}
/*if ( ncount[threadIdx.x] < MAX_NBR ) {
bufNeighbor [ nbr + ncount[threadIdx.x] ] = curr;
bufNdist [ nbr + ncount[threadIdx.x] ] = sqrt(dsq);
ncount[threadIdx.x]++;
}*/
__global__ void computePressure ( char* bufPntSort, int* bufGrid, uint2* bufHash, int numPnt )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
//if ( ndx < 1024 ) {
float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride));
// Find 2x2x2 grid cells
// - Use registers only, no arrays (local-memory too slow)
int3 cell;
int gc0, gc1, gc2, gc3, gc4, gc5, gc6, gc7;
float gs = simData.smooth_rad / simData.sim_scale;
cell.x = max(0, (int)((-gs + pos->x - simData.min.x) * simData.delta.x));
cell.y = max(0, (int)((-gs + pos->y - simData.min.y) * simData.delta.y));
cell.z = max(0, (int)((-gs + pos->z - simData.min.z) * simData.delta.z));
gc0 = __mul24(__mul24(cell.z, simData.res.y) + cell.y, simData.res.x) + cell.x;
gc1 = gc0 + 1;
gc2 = gc0 + simData.res.x;
gc3 = gc2 + 1;
if ( cell.z+1 < simData.res.z ) {
gc4 = gc0 + __mul24(simData.res.x, simData.res.y);
gc5 = gc4 + 1;
gc6 = gc4 + simData.res.x;
gc7 = gc6 + 1;
}
if ( cell.x+1 >= simData.res.x ) {
gc1 = -1; gc3 = -1;
gc5 = -1; gc7 = -1;
}
if ( cell.y+1 >= simData.res.y ) {
gc2 = -1; gc3 = -1;
gc6 = -1; gc7 = -1;
}
// Sum Pressure
float sum = 0.0;
bufNeighbor[ __mul24(ndx, MAX_NBR) ] = 1;
if (gc0 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc0], gc0, bufPntSort, bufHash );
if (gc1 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc1], gc1, bufPntSort, bufHash );
if (gc2 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc2], gc2, bufPntSort, bufHash );
if (gc3 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc3], gc3, bufPntSort, bufHash );
if (gc4 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc4], gc4, bufPntSort, bufHash );
if (gc5 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc5], gc5, bufPntSort, bufHash );
if (gc6 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc6], gc6, bufPntSort, bufHash );
if (gc7 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc7], gc7, bufPntSort, bufHash );
// Compute Density & Pressure
sum = sum * simData.pmass * simData.poly6kern;
if ( sum == 0.0 ) sum = 1.0;
*(float*) ((char*)pos + OFFSET_PRESS) = ( sum - simData.rest_dens ) * simData.stiffness;
*(float*) ((char*)pos + OFFSET_DENS) = 1.0f / sum;
//}
//__syncthreads ();
}
__device__ void contributeForce ( float3& force, int pndx, float3* p, int qndx, int grid_ndx, char* bufPnts, uint2* bufHash )
{
float press = *(float*) ((char*)p + OFFSET_PRESS);
float dens = *(float*) ((char*)p + OFFSET_DENS);
float3 veval = *(float3*) ((char*)p + OFFSET_VEVAL );
float3 qeval, dist;
float c, ndistj, dsq;
float pterm, dterm, vterm;
float3* qpos;
float d = simData.sim_scale;
vterm = simData.lapkern * simData.visc;
for ( ; qndx < simData.pnts; qndx++ ) {
if ( bufHash[qndx].x != grid_ndx || qndx == NULL_HASH) break;
if ( qndx != pndx ) {
qpos = (float3*) ( bufPnts + __mul24(qndx, simData.stride ));
dist.x = ( p->x - qpos->x )*d; // dist in cm
dist.y = ( p->y - qpos->y )*d;
dist.z = ( p->z - qpos->z )*d;
dsq = (dist.x*dist.x + dist.y*dist.y + dist.z*dist.z);
if ( dsq < simData.r2 ) {
ndistj = sqrt(dsq);
c = ( simData.smooth_rad - ndistj );
dist.x = ( p->x - qpos->x )*d; // dist in cm
dist.y = ( p->y - qpos->y )*d;
dist.z = ( p->z - qpos->z )*d;
pterm = -0.5f * c * simData.spikykern * ( press + *(float*)((char*)qpos+OFFSET_PRESS) ) / ndistj;
dterm = c * dens * *(float*)((char*)qpos+OFFSET_DENS);
qeval = *(float3*)((char*)qpos+OFFSET_VEVAL);
force.x += ( pterm * dist.x + vterm * ( qeval.x - veval.x )) * dterm;
force.y += ( pterm * dist.y + vterm * ( qeval.y - veval.y )) * dterm;
force.z += ( pterm * dist.z + vterm * ( qeval.z - veval.z )) * dterm;
}
}
}
}
__global__ void computeForce ( char* bufPntSort, int* bufGrid, uint2* bufHash, int numPnt )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
//if ( ndx < numPnt ) {
float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride));
// Find 2x2x2 grid cells
// - Use registers only, no arrays (local-memory too slow)
int3 cell;
int gc0, gc1, gc2, gc3, gc4, gc5, gc6, gc7;
float gs = simData.smooth_rad / simData.sim_scale;
cell.x = max(0, (int)((-gs + pos->x - simData.min.x) * simData.delta.x));
cell.y = max(0, (int)((-gs + pos->y - simData.min.y) * simData.delta.y));
cell.z = max(0, (int)((-gs + pos->z - simData.min.z) * simData.delta.z));
gc0 = __mul24(__mul24(cell.z, simData.res.y) + cell.y, simData.res.x) + cell.x;
gc1 = gc0 + 1;
gc2 = gc0 + simData.res.x;
gc3 = gc2 + 1;
if ( cell.z+1 < simData.res.z ) {
gc4 = gc0 + __mul24(simData.res.x, simData.res.y);
gc5 = gc4 + 1;
gc6 = gc4 + simData.res.x;
gc7 = gc6 + 1;
}
if ( cell.x+1 >= simData.res.x ) {
gc1 = -1; gc3 = -1;
gc5 = -1; gc7 = -1;
}
if ( cell.y+1 >= simData.res.y ) {
gc2 = -1; gc3 = -1;
gc6 = -1; gc7 = -1;
}
// Sum Pressure
float3 force = make_float3(0,0,0);
if (gc0 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc0], gc0, bufPntSort, bufHash );
if (gc1 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc1], gc1, bufPntSort, bufHash );
if (gc2 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc2], gc2, bufPntSort, bufHash );
if (gc3 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc3], gc3, bufPntSort, bufHash );
if (gc4 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc4], gc4, bufPntSort, bufHash );
if (gc5 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc5], gc5, bufPntSort, bufHash );
if (gc6 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc6], gc6, bufPntSort, bufHash );
if (gc7 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc7], gc7, bufPntSort, bufHash );
// Update Force
*(float3*) ((char*)pos + OFFSET_FORCE ) = force;
//}
//__syncthreads ();
}
__global__ void computeForceNbr ( char* bufPntSort, int numPnt )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
if ( ndx < numPnt ) {
float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride));
float3* qpos;
float press = *(float*) ((char*)pos + OFFSET_PRESS);
float dens = *(float*) ((char*)pos + OFFSET_DENS);
float3 veval = *(float3*) ((char*)pos + OFFSET_VEVAL );
float3 qeval, dist, force;
float d = simData.sim_scale;
float c, ndistj;
float pterm, dterm, vterm;
vterm = simData.lapkern * simData.visc;
int nbr = __mul24(ndx, MAX_NBR);
int ncnt = bufNeighbor[ nbr ];
force = make_float3(0,0,0);
for (int j=1; j < ncnt; j++) { // base 1, n[0] = count
ndistj = bufNdist[ nbr+j ];
qpos = (float3*) (bufPntSort + __mul24( bufNeighbor[ nbr+j ], simData.stride) );
c = ( simData.smooth_rad - ndistj );
dist.x = ( pos->x - qpos->x )*d; // dist in cm
dist.y = ( pos->y - qpos->y )*d;
dist.z = ( pos->z - qpos->z )*d;
pterm = -0.5f * c * simData.spikykern * ( press + *(float*)((char*)qpos+OFFSET_PRESS) ) / ndistj;
dterm = c * dens * *(float*)((char*)qpos+OFFSET_DENS);
qeval = *(float3*)((char*)qpos+OFFSET_VEVAL);
force.x += ( pterm * dist.x + vterm * ( qeval.x - veval.x )) * dterm;
force.y += ( pterm * dist.y + vterm * ( qeval.y - veval.y )) * dterm;
force.z += ( pterm * dist.z + vterm * ( qeval.z - veval.z )) * dterm;
}
*(float3*) ((char*)pos + OFFSET_FORCE ) = force;
}
}
__global__ void advanceParticles ( char* bufPntSort, int numPnt, float dt, float ss )
{
uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index
if ( ndx < numPnt ) {
// Get particle vars
float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride));
float3* vel = (float3*) ((char*)pos + OFFSET_VEL );
float3* vel_eval = (float3*) ((char*)pos + OFFSET_VEVAL );
float3 accel = *(float3*) ((char*)pos + OFFSET_FORCE );
float3 vcurr, vnext;
// Leapfrog integration
accel.x *= 0.00020543; // NOTE - To do: SPH_PMASS should be passed in
accel.y *= 0.00020543;
accel.z *= 0.00020543;
accel.z -= 9.8;
vcurr = *vel;
vnext.x = accel.x*dt + vcurr.x;
vnext.y = accel.y*dt + vcurr.y;
vnext.z = accel.z*dt + vcurr.z; // v(t+1/2) = v(t-1/2) + a(t) dt
accel.x = (vcurr.x + vnext.x) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
accel.y = (vcurr.y + vnext.y) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
accel.z = (vcurr.z + vnext.z) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
*vel_eval = accel;
*vel = vnext;
dt /= simData.sim_scale;
vnext.x = pos->x + vnext.x*dt;
vnext.y = pos->y + vnext.y*dt;
vnext.z = pos->z + vnext.z*dt;
*pos = vnext; // p(t+1) = p(t) + v(t+1/2) dt
}
__syncthreads ();
}
#endif

View File

@@ -0,0 +1,45 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _PARTICLES_KERNEL_H_
#define _PARTICLES_KERNEL_H_
#include <stdio.h>
#include <math.h>
#include "cutil_math.h"
#include "math_constants.h"
// Insert particles in grid
__global__ void insertParticles ( char* pntData, uint pntStride )
{
int index = __mul24(blockIdx.x,blockDim.x) + threadIdx.x;
float4 p = *(float4*) (pntData + index*pntStride);
// get address in grid
int3 gridPos = calcGridPos(p);
addParticleToCell(gridPos, index, gridCounters, gridCells);
}
#endif

View File

@@ -0,0 +1,79 @@
/*
* Copyright 1993-2006 NVIDIA Corporation. All rights reserved.
*
* NOTICE TO USER:
*
* This source code is subject to NVIDIA ownership rights under U.S. and
* international Copyright laws.
*
* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
* IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
* OR PERFORMANCE OF THIS SOURCE CODE.
*
* U.S. Government End Users. This source code is a "commercial item" as
* that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of
* "commercial computer software" and "commercial computer software
* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995)
* and is provided to the U.S. Government only as a commercial end item.
* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through
* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
* source code with only those rights set forth herein.
*/
/* Radixsort project with key/value and arbitrary datset size support
* which demonstrates the use of CUDA in a multi phase sorting
* computation.
* Host code.
*/
#include "radixsort.cuh"
#include "radixsort_kernel.cu"
extern "C"
{
////////////////////////////////////////////////////////////////////////////////
//! Perform a radix sort
//! Sorting performed in place on passed arrays.
//!
//! @param pData0 input and output array - data will be sorted
//! @param pData1 additional array to allow ping pong computation
//! @param elements number of elements to sort
////////////////////////////////////////////////////////////////////////////////
void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits)
{
// Round element count to total number of threads for efficiency
uint elements_rounded_to_3072;
int modval = elements % 3072;
if( modval == 0 )
elements_rounded_to_3072 = elements;
else
elements_rounded_to_3072 = elements + (3072 - (modval));
// Iterate over n bytes of y bit word, using each byte to sort the list in turn
for (uint shift = 0; shift < bits; shift += RADIX)
{
// Perform one round of radix sorting
// Generate per radix group sums radix counts across a radix group
RadixSum<<<NUM_BLOCKS, NUM_THREADS_PER_BLOCK, GRFSIZE>>>(pData0, elements, elements_rounded_to_3072, shift);
// Prefix sum in radix groups, and then between groups throughout a block
RadixPrefixSum<<<PREFIX_NUM_BLOCKS, PREFIX_NUM_THREADS_PER_BLOCK, PREFIX_GRFSIZE>>>();
// Sum the block offsets and then shuffle data into bins
RadixAddOffsetsAndShuffle<<<NUM_BLOCKS, NUM_THREADS_PER_BLOCK, SHUFFLE_GRFSIZE>>>(pData0, pData1, elements, elements_rounded_to_3072, shift);
// Exchange data pointers
KeyValuePair* pTemp = pData0;
pData0 = pData1;
pData1 = pTemp;
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 1993-2006 NVIDIA Corporation. All rights reserved.
*
* NOTICE TO USER:
*
* This source code is subject to NVIDIA ownership rights under U.S. and
* international Copyright laws.
*
* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
* IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
* OR PERFORMANCE OF THIS SOURCE CODE.
*
* U.S. Government End Users. This source code is a "commercial item" as
* that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of
* "commercial computer software" and "commercial computer software
* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995)
* and is provided to the U.S. Government only as a commercial end item.
* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through
* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
* source code with only those rights set forth herein.
*/
/* Radixsort project which demonstrates the use of CUDA in a multi phase
* sorting computation.
* Type definitions.
*/
#ifndef _RADIXSORT_H_
#define _RADIXSORT_H_
#include <host_defines.h>
#define SYNCIT __syncthreads()
// Use 16 bit keys/values
#define SIXTEEN 0
typedef unsigned int uint;
typedef unsigned short ushort;
#if SIXTEEN
typedef struct __align__(4) {
ushort key;
ushort value;
#else
typedef struct __align__(8) {
uint key;
uint value;
#endif
} KeyValuePair;
extern "C" {
void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits);
}
#endif // #ifndef _RADIXSORT_H_

View File

@@ -0,0 +1,577 @@
/*
* Copyright 1993-2006 NVIDIA Corporation. All rights reserved.
*
* NOTICE TO USER:
*
* This source code is subject to NVIDIA ownership rights under U.S. and
* international Copyright laws.
*
* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
* IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
* OR PERFORMANCE OF THIS SOURCE CODE.
*
* U.S. Government End Users. This source code is a "commercial item" as
* that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of
* "commercial computer software" and "commercial computer software
* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995)
* and is provided to the U.S. Government only as a commercial end item.
* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through
* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
* source code with only those rights set forth herein.
*/
/* Radixsort project with key/value and arbitrary datset size support
* which demonstrates the use of CUDA in a multi phase sorting
* computation.
* Device code.
*/
#ifndef _RADIXSORT_KERNEL_H_
#define _RADIXSORT_KERNEL_H_
#include <stdio.h>
#include "radixsort.cuh"
#define SYNCIT __syncthreads()
static const int NUM_SMS = 16;
static const int NUM_THREADS_PER_SM = 192;
static const int NUM_THREADS_PER_BLOCK = 64;
//static const int NUM_THREADS = NUM_THREADS_PER_SM * NUM_SMS;
static const int NUM_BLOCKS = (NUM_THREADS_PER_SM / NUM_THREADS_PER_BLOCK) * NUM_SMS;
static const int RADIX = 8; // Number of bits per radix sort pass
static const int RADICES = 1 << RADIX; // Number of radices
static const int RADIXMASK = RADICES - 1; // Mask for each radix sort pass
#if SIXTEEN
static const int RADIXBITS = 16; // Number of bits to sort over
#else
static const int RADIXBITS = 32; // Number of bits to sort over
#endif
static const int RADIXTHREADS = 16; // Number of threads sharing each radix counter
static const int RADIXGROUPS = NUM_THREADS_PER_BLOCK / RADIXTHREADS; // Number of radix groups per CTA
static const int TOTALRADIXGROUPS = NUM_BLOCKS * RADIXGROUPS; // Number of radix groups for each radix
static const int SORTRADIXGROUPS = TOTALRADIXGROUPS * RADICES; // Total radix count
static const int GRFELEMENTS = (NUM_THREADS_PER_BLOCK / RADIXTHREADS) * RADICES;
static const int GRFSIZE = GRFELEMENTS * sizeof(uint);
// Prefix sum variables
static const int PREFIX_NUM_THREADS_PER_SM = NUM_THREADS_PER_SM;
static const int PREFIX_NUM_THREADS_PER_BLOCK = PREFIX_NUM_THREADS_PER_SM;
static const int PREFIX_NUM_BLOCKS = (PREFIX_NUM_THREADS_PER_SM / PREFIX_NUM_THREADS_PER_BLOCK) * NUM_SMS;
static const int PREFIX_BLOCKSIZE = SORTRADIXGROUPS / PREFIX_NUM_BLOCKS;
static const int PREFIX_GRFELEMENTS = PREFIX_BLOCKSIZE + 2 * PREFIX_NUM_THREADS_PER_BLOCK;
static const int PREFIX_GRFSIZE = PREFIX_GRFELEMENTS * sizeof(uint);
// Shuffle variables
static const int SHUFFLE_GRFOFFSET = RADIXGROUPS * RADICES;
static const int SHUFFLE_GRFELEMENTS = SHUFFLE_GRFOFFSET + PREFIX_NUM_BLOCKS;
static const int SHUFFLE_GRFSIZE = SHUFFLE_GRFELEMENTS * sizeof(uint);
#define SDATA( index) CUT_BANK_CHECKER(sdata, index)
// Prefix sum data
uint gRadixSum[TOTALRADIXGROUPS * RADICES];
__device__ uint dRadixSum[TOTALRADIXGROUPS * RADICES];
uint gRadixBlockSum[PREFIX_NUM_BLOCKS];
__device__ uint dRadixBlockSum[PREFIX_NUM_BLOCKS];
extern __shared__ uint sRadixSum[];
////////////////////////////////////////////////////////////////////////////////
//! Perform a radix sum on the list to be sorted. Each SM holds a set of
//! radix counters for each group of RADIXGROUPS thread in the GRF.
//!
//! @param pData input data
//! @param elements total number of elements
//! @param elements_rounded_to_3072 total number of elements rounded up to the
//! nearest multiple of 3072
//! @param shift the shift (0 to 24) that we are using to obtain the correct
//! byte
////////////////////////////////////////////////////////////////////////////////
__global__ void RadixSum(KeyValuePair *pData, uint elements, uint elements_rounded_to_3072, uint shift)
{
uint pos = threadIdx.x;
// Zero radix counts
while (pos < GRFELEMENTS)
{
sRadixSum[pos] = 0;
pos += NUM_THREADS_PER_BLOCK;
}
// Sum up data
// Source addresses computed so that each thread is reading from a block of
// consecutive addresses so there are no conflicts between threads
// They then loop over their combined region and the next batch works elsewhere.
// So threads 0 to 16 work on memory 0 to 320.
// First reading 0,1,2,3...15 then 16,17,18,19...31 and so on
// optimising parallel access to shared memory by a thread accessing 16*threadID
// The next radix group runs from 320 to 640 and the same applies in that region
uint tmod = threadIdx.x % RADIXTHREADS;
uint tpos = threadIdx.x / RADIXTHREADS;
// Take the rounded element list size so that all threads have a certain size dataset to work with
// and no zero size datasets confusing the issue
// By using a multiple of 3072 we ensure that all threads have elements
// to work with until the last phase, at which point we individually test
uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS;
// Generate range
// Note that it is possible for both pos and end to be past the end of the element set
// which will be caught later.
pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction;
uint end = pos + element_fraction;
pos += tmod;
//printf("pos: %d\n", pos);
__syncthreads();
while (pos < end )
{
uint key = 0;
// Read first data element if we are in the set of elements
//if( pos < elements )
//key = pData[pos].key;
KeyValuePair kvp;
// Read first data element, both items at once as the memory will want to coalesce like that anyway
if (pos < elements)
kvp = pData[pos];
else
kvp.key = 0;
key = kvp.key;
// Calculate position of radix counter to increment
// There are RADICES radices in each pass (256)
// and hence this many counters for bin grouping
// Multiply by RADIXGROUPS (4) to spread through memory
// and into 4 radix groups
uint p = ((key >> shift) & RADIXMASK) * RADIXGROUPS;
// Increment radix counters
// Each radix group has its own set of counters
// so we add the thread position [0-3], ie the group index.
// We slow down here and take at least 16 cycles to write to the summation boxes
// but other groups will only conflict with themselves and so can also be writing
// 16 cycles here at least avoids retries.
uint ppos = p + tpos;
// If we are past the last element we don't want to do anything
// We do have to check each time, however, to ensure that all
// threads sync on each sync here.
if (tmod == 0 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 1 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 2 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 3 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 4 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 5 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 6 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 7 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 8 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 9 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 10 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 11 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 12 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 13 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 14 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
if (tmod == 15 && pos < elements)
sRadixSum[ppos]++;
SYNCIT;
pos += RADIXTHREADS;
}
__syncthreads();
__syncthreads();
// Output radix sums into separate memory regions for each radix group
// So this memory then is layed out:
// 0...... 192..... 384 ................ 192*256
// ie all 256 bins for each radix group
// in there:
// 0.............192
// 0 4 8 12... - block idx * 4
// And in the block boxes we see the 4 radix groups for that block
// So 0-192 should contain bin 0 for each radix group, and so on
uint offset = blockIdx.x * RADIXGROUPS;
uint row = threadIdx.x / RADIXGROUPS;
uint column = threadIdx.x % RADIXGROUPS;
while (row < RADICES)
{
dRadixSum[offset + row * TOTALRADIXGROUPS + column] = sRadixSum[row * RADIXGROUPS + column];
row += NUM_THREADS_PER_BLOCK / RADIXGROUPS;
}
}
////////////////////////////////////////////////////////////////////////////////
//! Performs first part of parallel prefix sum - individual sums of each radix
//! count. By the end of this we have prefix sums on a block level in dRadixSum
//! and totals for blocks in dRadixBlockSum.
////////////////////////////////////////////////////////////////////////////////
__global__ void RadixPrefixSum()
{
// Read radix groups in offset by one in the GRF so a zero can be inserted at the beginning
// and the final sum of all radix counts summed here is tacked onto the end for reading by
// the next stage
// Each block in this case is the full number of threads per SM (and hence the total number
// of radix groups), 192. We should then have the total set of offsets for an entire radix
// group by the end of this stage
// Device mem addressing
uint brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS);
uint drow = threadIdx.x / TOTALRADIXGROUPS; // In default parameterisation this is always 0
uint dcolumn = threadIdx.x % TOTALRADIXGROUPS; // And similarly this is always the same as threadIdx.x
uint dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn;
uint end = ((blockIdx.x + 1) * (RADICES / PREFIX_NUM_BLOCKS)) * TOTALRADIXGROUPS;
// Shared mem addressing
uint srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
uint scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
uint spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn;
// Read (RADICES / PREFIX_NUM_BLOCKS) radix counts into the GRF alongside each other
while (dpos < end)
{
sRadixSum[spos] = dRadixSum[dpos];
spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) *
(PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1);
dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS;
}
__syncthreads();
// Perform preliminary sum on each thread's stretch of data
// Each thread having a block of 16, with spacers between 0...16 18...33 and so on
int pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1);
end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
uint sum = 0;
while (pos < end)
{
sum += sRadixSum[pos];
sRadixSum[pos] = sum;
pos++;
}
__syncthreads();
// Calculate internal offsets by performing a more traditional parallel
// prefix sum of the topmost member of each thread's work data. Right now,
// these are stored between the work data for each thread, allowing us to
// eliminate GRF conflicts as well as hold the offsets needed to complete the sum
// In other words we have:
// 0....15 16 17....32 33 34....
// Where this first stage updates the intermediate values (so 16=15, 33=32 etc)
int m = (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1);
pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) +
(PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
sRadixSum[pos] = sRadixSum[pos - 1];
__syncthreads();
// This stage then performs a parallel prefix sum (ie use powers of 2 to propagate in log n stages)
// to update 17, 34 etc with the totals to that point (so 34 becomes [34] + [17]) and so on.
while (m < PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1))
{
int p = pos - m;
uint t = ((p > 0) ? sRadixSum[p] : 0);
__syncthreads();
sRadixSum[pos] += t;
__syncthreads();
m *= 2;
}
__syncthreads();
// Add internal offsets to each thread's work data.
// So now we take 17 and add it to all values 18 to 33 so all offsets for that block
// are updated.
pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1);
end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
int p = pos - 1;
sum = ((p > 0) ? sRadixSum[p] : 0);
while (pos < end)
{
sRadixSum[pos] += sum;
pos++;
}
__syncthreads();
// Write summed data back out to global memory in the same way as we read it in
// We now have prefix sum values internal to groups
brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS);
drow = threadIdx.x / TOTALRADIXGROUPS;
dcolumn = threadIdx.x % TOTALRADIXGROUPS;
srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK);
dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn + 1;
spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn;
end = ((blockIdx.x + 1) * RADICES / PREFIX_NUM_BLOCKS) * TOTALRADIXGROUPS;
while (dpos < end)
{
dRadixSum[dpos] = sRadixSum[spos];
dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS;
spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) *
(PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1);
}
// Write last element to summation
// Storing block sums in a separate array
if (threadIdx.x == 0) {
dRadixBlockSum[blockIdx.x] = sRadixSum[PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) - 1];
dRadixSum[blockIdx.x * PREFIX_BLOCKSIZE] = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
//! Initially perform prefix sum of block totals to obtain final set of offsets.
//! Then make use of radix sums to perform a shuffling of the data into the
//! correct bins.
//!
//! @param pSrc input data
//! @param pDst output data
//! @param elements total number of elements
//! @param shift the shift (0 to 24) that we are using to obtain the correct
//! byte
////////////////////////////////////////////////////////////////////////////////
__global__ void RadixAddOffsetsAndShuffle(KeyValuePair* pSrc, KeyValuePair* pDst, uint elements, uint elements_rounded_to_3072, int shift)
{
// Read offsets from previous blocks
if (threadIdx.x == 0)
sRadixSum[SHUFFLE_GRFOFFSET] = 0;
if (threadIdx.x < PREFIX_NUM_BLOCKS - 1)
sRadixSum[SHUFFLE_GRFOFFSET + threadIdx.x + 1] = dRadixBlockSum[threadIdx.x];
__syncthreads();
// Parallel prefix sum over block sums
int pos = threadIdx.x;
int n = 1;
while (n < PREFIX_NUM_BLOCKS)
{
int ppos = pos - n;
uint t0 = ((pos < PREFIX_NUM_BLOCKS) && (ppos >= 0)) ? sRadixSum[SHUFFLE_GRFOFFSET + ppos] : 0;
__syncthreads();
if (pos < PREFIX_NUM_BLOCKS)
sRadixSum[SHUFFLE_GRFOFFSET + pos] += t0;
__syncthreads();
n *= 2;
}
// Read radix count data and add appropriate block offset
// for each radix at the memory location for this thread
// (where the other threads in the block will be reading
// as well, hence the large stride).
// There is one counter box per radix group per radix
// per block (4*256*3)
// We use 64 threads to read the 4 radix groups set of radices
// for the block.
int row = threadIdx.x / RADIXGROUPS;
int column = threadIdx.x % RADIXGROUPS;
int spos = row * RADIXGROUPS + column;
int dpos = row * TOTALRADIXGROUPS + column + blockIdx.x * RADIXGROUPS;
while (spos < SHUFFLE_GRFOFFSET)
{
sRadixSum[spos] = dRadixSum[dpos] + sRadixSum[SHUFFLE_GRFOFFSET + dpos / (TOTALRADIXGROUPS * RADICES / PREFIX_NUM_BLOCKS)];
spos += NUM_THREADS_PER_BLOCK;
dpos += (NUM_THREADS_PER_BLOCK / RADIXGROUPS) * TOTALRADIXGROUPS;
}
__syncthreads();
//int pos;
// Shuffle data
// Each of the subbins for a block should be filled via the counters, properly interleaved
// Then, as we now iterate over each data value, we increment the subbins (each thread in the
// radix group in turn to avoid miss writes due to conflicts) and set locations correctly.
uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS;
int tmod = threadIdx.x % RADIXTHREADS;
int tpos = threadIdx.x / RADIXTHREADS;
pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction;
uint end = pos + element_fraction; //(blockIdx.x * RADIXGROUPS + tpos + 1) * element_fraction;
pos += tmod;
__syncthreads();
while (pos < end )
{
KeyValuePair kvp;
#if 1 // old load
// Read first data element, both items at once as the memory will want to coalesce like that anyway
if (pos < elements)
{
kvp = pSrc[pos];
}
else
kvp.key = 0;
#else // casting to float2 to get it to combine loads
int2 kvpf2;
// Read first data element, both items at once as the memory will want to coalesce like that anyway
if (pos < elements)
{
// kvp = pSrc[pos];
kvpf2 = ((int2*)pSrc)[pos];
// printf("kvp: %f %f kvpf2: %f %f\n", kvp.key, kvp.value, kvpf2.x, kvpf2.y);
}
else
//kvp.key = 0;
kvpf2.x = 0;
kvp.key = kvpf2.x;
kvp.value = kvpf2.y;
#endif
uint index;
// Calculate position of radix counter to increment
uint p = ((kvp.key >> shift) & RADIXMASK) * RADIXGROUPS;
// Move data, keeping counts updated.
// Increment radix counters, relying on hexadecathread
// warp to prevent this code from stepping all over itself.
uint ppos = p + tpos;
if (tmod == 0 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 1 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 2 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 3 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 4 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 5 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 6 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 7 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 8 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 9 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 10 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 11 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 12 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 13 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 14 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
if (tmod == 15 && pos < elements)
{
index = sRadixSum[ppos]++;
pDst[index] = kvp;
}
SYNCIT;
pos += RADIXTHREADS;
}
__syncthreads();
}
#endif // #ifndef _RADIXSORT_KERNEL_H_

View File

@@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fluids_2005", "fluids_2005.vcproj", "{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
EmuDebug|Win32 = EmuDebug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Debug|Win32.ActiveCfg = Debug|Win32
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Debug|Win32.Build.0 = Debug|Win32
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.EmuDebug|Win32.ActiveCfg = EmuDebug|Win32
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.EmuDebug|Win32.Build.0 = EmuDebug|Win32
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Release|Win32.ActiveCfg = Release|Win32
{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,447 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="fluids_2005"
ProjectGUID="{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}"
RootNamespace="fluids_2005"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="fluids;common;marching;marching_tris;C:\CUDA\common\inc"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="glee_2005.lib cudart.lib cutil32D.lib"
LinkIncremental="2"
IgnoreDefaultLibraryNames="libcmt.lib"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="C:\CUDA\common\inc;fluids;common;marching;marching_tris"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cudart.lib cutil32.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="C:\CUDA\common\lib;."
IgnoreDefaultLibraryNames="libcmtd.lib"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="EmuDebug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="fluids;common;marching"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="glee_VS2005.lib cg.lib cgGL.lib cudart.lib cutil32D.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/fluids_2005.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="common"
>
<File
RelativePath=".\common\common_defs.h"
>
</File>
<File
RelativePath=".\common\geomx.cpp"
>
</File>
<File
RelativePath=".\common\geomx.h"
>
</File>
<File
RelativePath=".\common\gl_helper.cpp"
>
</File>
<File
RelativePath=".\common\gl_helper.h"
>
</File>
<File
RelativePath=".\common\image.cpp"
>
</File>
<File
RelativePath=".\common\image.h"
>
</File>
<File
RelativePath=".\common\matrix-inline.h"
>
</File>
<File
RelativePath=".\common\matrix.cpp"
>
</File>
<File
RelativePath=".\common\matrix.h"
>
</File>
<File
RelativePath=".\common\mdebug.cpp"
>
</File>
<File
RelativePath=".\common\mdebug.h"
>
</File>
<File
RelativePath=".\common\mesh.cpp"
>
</File>
<File
RelativePath=".\common\mesh.h"
>
</File>
<File
RelativePath=".\common\mesh_info.h"
>
</File>
<File
RelativePath=".\common\mtime.cpp"
>
</File>
<File
RelativePath=".\common\mtime.h"
>
</File>
<File
RelativePath=".\common\particle.cpp"
>
</File>
<File
RelativePath=".\common\particle.h"
>
</File>
<File
RelativePath=".\common\point_set.cpp"
>
</File>
<File
RelativePath=".\common\point_set.h"
>
</File>
<File
RelativePath=".\common\vector-inline.h"
>
</File>
<File
RelativePath=".\common\vector.cpp"
>
</File>
<File
RelativePath=".\common\vector.h"
>
</File>
</Filter>
<Filter
Name="fluids"
>
<File
RelativePath=".\fluids\fluid.cpp"
>
</File>
<File
RelativePath=".\fluids\fluid.h"
>
</File>
<File
RelativePath=".\fluids\fluid_system.cpp"
>
</File>
<File
RelativePath=".\fluids\fluid_system.h"
>
</File>
<File
RelativePath=".\fluids\fluid_system_host.cu"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="&quot;$(CUDA_BIN_PATH)\nvcc.exe&quot; -arch=sm_10 -ccbin &quot;$(VCInstallDir)\bin&quot; -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I &quot;$(CUDA_INC_PATH)&quot;; -I./ -o $(ConfigurationName)\fluid_system_cu.obj fluids\fluid_system_host.cu&#x0D;&#x0A;"
AdditionalDependencies="fluid_system_host.cuh; fluid_system_kern.cu;"
Outputs="$(ConfigurationName)\fluid_system_cu.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="&quot;$(CUDA_BIN_PATH)\nvcc.exe&quot; -arch=sm_10 -use_fast_math -ccbin &quot;$(VCInstallDir)\bin&quot; -c -I &quot;$(CUDA_INC_PATH)&quot;; -I./ -I../../common/inc -o $(ConfigurationName)\fluid_system_cu.obj fluids\fluid_system_host.cu&#x0D;&#x0A;"
AdditionalDependencies="fluid_system_host.cuh; fluid_system_kern.cu; radixsort.cu"
Outputs="$(ConfigurationName)\fluid_system_cu.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="EmuDebug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="&quot;$(CUDA_BIN_PATH)\nvcc.exe&quot; -arch=sm_10 -ccbin &quot;$(VCInstallDir)\bin&quot; -deviceemu -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I &quot;$(CUDA_INC_PATH)&quot;; -I./ -o $(ConfigurationName)\fluid_system_cu.obj fluids\fluid_system_host.cu&#x0D;&#x0A;"
AdditionalDependencies="fluid_system_host.cuh; fluid_system_kern.cu;"
Outputs="$(ConfigurationName)\fluid_system_cu.obj"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\fluids\fluid_system_host.cuh"
>
</File>
<File
RelativePath=".\fluids\fluid_system_kern.cu"
>
</File>
</Filter>
<Filter
Name="radix_sort"
>
<File
RelativePath=".\radixsort.cu"
>
</File>
<File
RelativePath=".\radixsort.cuh"
>
</File>
<File
RelativePath=".\radixsort_kernel.cu"
>
</File>
</Filter>
<File
RelativePath=".\common\GLee.c"
>
</File>
<File
RelativePath=".\common\GLee.h"
>
</File>
<File
RelativePath=".\main.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fluids", "fluids.vcproj", "{F9F0795D-4C39-41F4-9381-25C616D69FB2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F9F0795D-4C39-41F4-9381-25C616D69FB2}.Debug|Win32.ActiveCfg = Debug|Win32
{F9F0795D-4C39-41F4-9381-25C616D69FB2}.Debug|Win32.Build.0 = Debug|Win32
{F9F0795D-4C39-41F4-9381-25C616D69FB2}.Release|Win32.ActiveCfg = Release|Win32
{F9F0795D-4C39-41F4-9381-25C616D69FB2}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

585
Extras/sph/main.cpp Normal file
View File

@@ -0,0 +1,585 @@
/*
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
ZLib license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <time.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "common_defs.h"
#ifdef BUILD_CUDA
#include "fluid_system_host.cuh"
#endif
#include "fluid_system.h"
#include "gl_helper.h"
#ifdef _MSC_VER // Windows
#include <gl/glut.h>
#else // Linux
#include <GL/glut.h>
#endif
bool bTiming = false;
bool bRec = false;
int mFrame = 0;
// Globals
FluidSystem psys;
float window_width = 1024;
float window_height = 768;
Vector3DF cam_from, cam_angs, cam_to; // Camera stuff
Vector3DF obj_from, obj_angs, obj_dang;
Vector3DF light[2], light_to[2]; // Light stuff
float light_fov, cam_fov;
int psys_rate = 0; // Particle stuff
int psys_freq = 1;
int psys_demo = 0;
int psys_nmax = 4096;
bool bHelp = false; // Toggles
int iShade = 1;
int iClrMode = 0;
bool bPntDraw = false;
bool bPause = false;
// View matricies
float view_matrix[16]; // View matrix (V)
float model_matrix[16]; // Model matrix (M)
float proj_matrix[16]; // Projective matrix
// Mouse control
#define DRAG_OFF 0 // mouse states
#define DRAG_LEFT 1
#define DRAG_RIGHT 2
int last_x = -1, last_y = -1; // mouse vars
int mode = 0;
int dragging = 0;
int psel;
GLuint screen_id;
GLuint depth_id;
// Different things we can move around
#define MODE_CAM 0
#define MODE_CAM_TO 1
#define MODE_OBJ 2
#define MODE_OBJPOS 3
#define MODE_OBJGRP 4
#define MODE_LIGHTPOS 5
#define MODE_DOF 6
GLuint screenBufferObject;
GLuint depthBufferObject;
GLuint envid;
void drawScene ( float* viewmat, bool bShade )
{
if ( iShade <= 1 && bShade ) {
glEnable ( GL_LIGHT0 );
GLfloat diff[4];
GLfloat spec[4];
GLfloat shininess = 60.0;
diff[0] = 0.8f; diff[1] = 0.8f; diff[2] = 0.8f; diff[3] = 1.0f;
spec[0] = 1.0f; spec[1] = 1.0f; spec[2] = 1.0f; spec[3] = 1.0f;
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, &diff[0]);
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, &spec[0]);
glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glColor3f ( 1, 1, 1 );
glLoadMatrixf ( viewmat );
glBegin ( GL_QUADS );
glNormal3f ( 0, 0, 1 );
glVertex3f ( -1000, -1000, 0.0 );
glVertex3f ( 1000, -1000, 0.0 );
glVertex3f ( 1000, 1000, 0.0 );
glVertex3f ( -1000, 1000, 0.0 );
glEnd ();
glBegin ( GL_LINES );
for (float n=-100; n <= 100; n += 20.0 ) {
glVertex3f ( -100, n, 0.1 );
glVertex3f ( 100, n, 0.1 );
glVertex3f ( n, -100, 0.1 );
glVertex3f ( n, 100, 0.1 );
}
glEnd ();
psys.Draw ( &viewmat[0], 0.8 ); // Draw particles
} else {
glDisable ( GL_LIGHTING );
psys.Draw ( &viewmat[0], 0.55 ); // Draw particles
}
}
void draw2D ()
{
mint::Time start, stop;
#ifdef USE_SHADOWS
disableShadows ();
#endif
glDisable ( GL_LIGHTING );
glDisable ( GL_DEPTH_TEST );
glMatrixMode ( GL_PROJECTION );
glLoadIdentity ();
glScalef ( 2.0/window_width, -2.0/window_height, 1 ); // Setup view (0,0) to (800,600)
glTranslatef ( -window_width/2.0, -window_height/2, 0.0);
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ();
glPushMatrix ();
glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix );
glPopMatrix ();
char disp[200];
glColor4f ( 1.0, 1.0, 1.0, 1.0 );
strcpy ( disp, "Press H for help." ); drawText ( 10, 20, disp );
if ( bHelp ) {
if ( psys.GetToggle ( USE_CUDA ) ) {
sprintf ( disp, "Kernel: USING CUDA (GPU)" ); drawText ( 20, 40, disp );
} else {
sprintf ( disp, "Kernel: USING CPU" ); drawText ( 20, 40, disp );
}
sprintf ( disp, "KEYBOARD" ); drawText ( 20, 60, disp );
sprintf ( disp, "[ ] Next/Prev Demo" ); drawText ( 20, 70, disp );
sprintf ( disp, "N M Adjust Max Particles" ); drawText ( 20, 80, disp );
sprintf ( disp, "space Pause" ); drawText ( 20, 90, disp );
sprintf ( disp, "S Shading mode" ); drawText ( 20, 100, disp );
sprintf ( disp, "G Toggle CUDA vs CPU" ); drawText ( 20, 110, disp );
sprintf ( disp, "< > Change emitter rate" ); drawText ( 20, 120, disp );
sprintf ( disp, "C Move camera /w mouse" ); drawText ( 20, 130, disp );
sprintf ( disp, "I Move emitter /w mouse" ); drawText ( 20, 140, disp );
sprintf ( disp, "O Change emitter angle" ); drawText ( 20, 150, disp );
sprintf ( disp, "L Move light /w mouse" ); drawText ( 20, 160, disp );
sprintf ( disp, "X Draw velocity/pressure/color" ); drawText ( 20, 170, disp );
Vector3DF vol = psys.GetVec(SPH_VOLMAX);
vol -= psys.GetVec(SPH_VOLMIN);
sprintf ( disp, "Volume Size: %3.5f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 190, disp );
sprintf ( disp, "Time Step (dt): %3.5f", psys.GetDT () ); drawText ( 20, 200, disp );
sprintf ( disp, "Num Particles: %d", psys.NumPoints() ); drawText ( 20, 210, disp );
sprintf ( disp, "Simulation Scale: %3.5f", psys.GetParam(SPH_SIMSIZE) ); drawText ( 20, 220, disp );
sprintf ( disp, "Simulation Size (m): %3.5f", psys.GetParam(SPH_SIMSCALE) ); drawText ( 20, 230, disp );
sprintf ( disp, "Smooth Radius (m): %3.3f", psys.GetParam(SPH_SMOOTHRADIUS) ); drawText ( 20, 240, disp );
sprintf ( disp, "Particle Radius (m): %3.3f", psys.GetParam(SPH_PRADIUS) ); drawText ( 20, 250, disp );
sprintf ( disp, "Particle Mass (kg): %0.8f", psys.GetParam(SPH_PMASS) ); drawText ( 20, 260, disp );
sprintf ( disp, "Rest Density (kg/m^3): %3.3f", psys.GetParam(SPH_RESTDENSITY) ); drawText ( 20, 270, disp );
sprintf ( disp, "Viscosity: %3.3f", psys.GetParam(SPH_VISC) ); drawText ( 20, 280, disp );
sprintf ( disp, "Internal Stiffness: %3.3f", psys.GetParam(SPH_INTSTIFF) ); drawText ( 20, 290, disp );
sprintf ( disp, "Boundary Stiffness: %6.0f", psys.GetParam(SPH_EXTSTIFF) ); drawText ( 20, 300, disp );
sprintf ( disp, "Boundary Dampening: %4.3f", psys.GetParam(SPH_EXTDAMP) ); drawText ( 20, 310, disp );
sprintf ( disp, "Speed Limiting: %4.3f", psys.GetParam(SPH_LIMIT) ); drawText ( 20, 320, disp );
vol = psys.GetVec ( PLANE_GRAV_DIR );
sprintf ( disp, "Gravity: %3.2f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 330, disp );
}
}
void computeFromPositions ()
{
cam_from.x = cam_to.x + sin( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z;
cam_from.y = cam_to.y + -cos( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z;
cam_from.z = cam_to.z + cos( cam_angs.y * DEGtoRAD) * cam_angs.z;
}
void computeProjection ()
{
// ---- Create projection matrix for eye-coordinate transformations
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective ( cam_fov, window_width / ( float ) window_height, 10.0, 800.0 );
glPushMatrix ();
glGetFloatv ( GL_MODELVIEW_MATRIX, proj_matrix );
glPopMatrix ();
}
void computeView ()
{
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ();
gluLookAt ( cam_from.x, cam_from.y, cam_from.z, cam_to.x, cam_to.y, cam_to.z, 0, 0, 1 );
glPushMatrix ();
glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix );
glPopMatrix ();
}
int frame;
void display ()
{
mint::Time start, stop;
// iso = sin(frame*0.01f );
// Do simulation!
if ( !bPause ) psys.Run ();
frame++;
measureFPS ();
glEnable ( GL_DEPTH_TEST );
// Render depth map shadows
start.SetSystemTime ( ACC_NSEC );
disableShadows ();
#ifdef USE_SHADOWS
if ( iShade==1 ) {
renderDepthMap_FrameBuffer ( 0, window_width, window_height );
} else {
renderDepthMap_Clear ( window_width, window_height );
}
#endif
// Clear frame buffer
if ( iShade<=1 ) glClearColor( 0.29, 0.29, 0.29, 1.0 );
else glClearColor ( 0, 0, 0, 0 );
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDisable ( GL_CULL_FACE );
glShadeModel ( GL_SMOOTH );
// Compute camera view
computeFromPositions ();
computeProjection ();
computeView ();
// Draw Shadows (if on)
#ifdef USE_SHADOWS
if ( iShade==1 ) renderShadows ( view_matrix );
#endif
// Draw 3D
start.SetSystemTime ( ACC_NSEC );
glEnable ( GL_LIGHTING );
glLoadMatrixf ( view_matrix );
drawScene ( view_matrix, true );
if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "SCENE: %s\n", stop.GetReadableTime().c_str() ); }
// Draw 2D overlay
draw2D ();
// Swap buffers
glutSwapBuffers();
glutPostRedisplay();
}
void reshape ( int width, int height )
{
// set window height and width
window_width = (float) width;
window_height = (float) height;
glViewport( 0, 0, width, height );
}
void UpdateEmit ()
{
obj_from = psys.GetVec ( EMIT_POS );
obj_angs = psys.GetVec ( EMIT_ANG );
obj_dang = psys.GetVec ( EMIT_RATE );
}
void keyboard_func ( unsigned char key, int x, int y )
{
switch( key ) {
case 'M': case 'm': {
psys_nmax *= 2;
if ( psys_nmax > 65535 ) psys_nmax = 65535;
psys.SPH_CreateExample ( psys_demo, psys_nmax );
} break;
case 'N': case 'n': {
psys_nmax /= 2;
if ( psys_nmax < 64 ) psys_nmax = 64;
psys.SPH_CreateExample ( psys_demo, psys_nmax );
} break;
case '0':
UpdateEmit ();
psys_freq++;
psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
break;
case '9':
UpdateEmit ();
psys_freq--; if ( psys_freq < 0 ) psys_freq = 0;
psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
break;
case '.': case '>':
UpdateEmit ();
if ( ++psys_rate > 100 ) psys_rate = 100;
psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
break;
case ',': case '<':
UpdateEmit ();
if ( --psys_rate < 0 ) psys_rate = 0;
psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
break;
case 'g': case 'G': psys.Toggle ( USE_CUDA ); break;
case 'f': case 'F': mode = MODE_DOF; break;
case 'z': case 'Z': mode = MODE_CAM_TO; break;
case 'c': case 'C': mode = MODE_CAM; break;
case 'h': case 'H': bHelp = !bHelp; break;
case 'i': case 'I':
UpdateEmit ();
mode = MODE_OBJPOS;
break;
case 'o': case 'O':
UpdateEmit ();
mode = MODE_OBJ;
break;
case 'x': case 'X':
if ( ++iClrMode > 2) iClrMode = 0;
psys.SetParam ( CLR_MODE, iClrMode );
break;
case 'l': case 'L': mode = MODE_LIGHTPOS; break;
case 'd': case 'D': {
int d = psys.GetParam ( PNT_DRAWMODE ) + 1;
if ( d > 2 ) d = 0;
psys.SetParam ( PNT_DRAWMODE, d );
} break;
case 's': case 'S': if ( ++iShade > 2 ) iShade = 0; break;
case 27: exit( 0 ); break;
case '`':
bRec = !bRec; break;
case ' ':
//psys.Run (); ptris.Rebuild (); break;
bPause = !bPause; break;
case '\'': case ';': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break;
case 'r': case 'R': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break;
case '[':
psys_demo--;
if (psys_demo < 0 ) psys_demo = 10;
psys.SPH_CreateExample ( psys_demo, psys_nmax );
UpdateEmit ();
break;
case ']':
psys_demo++;
if (psys_demo > 10 ) psys_demo = 0;
psys.SPH_CreateExample ( psys_demo, psys_nmax );
UpdateEmit ();
break;
default:
break;
}
}
void mouse_click_func ( int button, int state, int x, int y )
{
if( state == GLUT_DOWN ) {
if ( button == GLUT_LEFT_BUTTON ) dragging = DRAG_LEFT;
else if ( button == GLUT_RIGHT_BUTTON ) dragging = DRAG_RIGHT;
last_x = x;
last_y = y;
} else {
dragging = DRAG_OFF;
}
}
void mouse_move_func ( int x, int y )
{
int dx = x - last_x;
int dy = y - last_y;
switch ( mode ) {
case MODE_CAM:
if ( dragging == DRAG_LEFT ) {
cam_angs.x += dx;
cam_angs.y += dy;
if ( cam_angs.x >= 360.0 ) cam_angs.x -= 360.0;
if ( cam_angs.x < 0 ) cam_angs.x += 360.0;
if ( cam_angs.y >= 180.0 ) cam_angs.y = 180.0;
if ( cam_angs.y <= -180.0 ) cam_angs.y = -180.0;
printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z );
printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z );
printf ( "Cam FOV: %f\n", cam_fov);
} else if ( dragging == DRAG_RIGHT ) {
cam_angs.z += dy*.15;
if ( cam_angs.z < 0) cam_angs.z = 0;
printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z );
printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z );
printf ( "Cam FOV: %f\n", cam_fov );
}
break;
case MODE_CAM_TO:
if ( dragging == DRAG_LEFT ) {
cam_to.x += dx;
cam_to.y += dy;
} else if ( dragging == DRAG_RIGHT ) {
cam_to.z += dy*.05;
if ( cam_to.z < 0) cam_to.z = 0;
}
break;
case MODE_OBJ:
if ( dragging == DRAG_LEFT ) {
obj_angs.x -= dx*0.1;
obj_angs.y += dy*0.1;
printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z );
//force_x += dx*.1;
//force_y += dy*.1;
} else if (dragging == DRAG_RIGHT) {
obj_angs.z -= dy*.005;
printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z );
}
psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) );
break;
case MODE_OBJPOS:
if ( dragging == DRAG_LEFT ) {
obj_from.x -= dx*.1;
obj_from.y += dy*.1;
printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z );
} else if (dragging == DRAG_RIGHT) {
obj_from.z -= dy*.1;
printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z );
}
psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) );
//psys.setPos ( obj_x, obj_y, obj_z, obj_ang, obj_tilt, obj_dist );
break;
case MODE_LIGHTPOS:
if ( dragging == DRAG_LEFT ) {
light[0].x -= dx*.1;
light[0].y += dy*.1;
printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z );
} else if (dragging == DRAG_RIGHT) {
light[0].z -= dy*.1;
printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z );
}
#ifdef USE_SHADOWS
setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov );
#endif
break;
}
if ( x < 10 || y < 10 || x > 1000 || y > 700 ) {
glutWarpPointer ( 1024/2, 768/2 );
last_x = 1024/2;
last_y = 768/2;
} else {
last_x = x;
last_y = y;
}
}
void idle_func ()
{
}
void init ()
{
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
srand ( time ( 0x0 ) );
glClearColor( 0.49, 0.49, 0.49, 1.0 );
glShadeModel( GL_SMOOTH );
glEnable ( GL_COLOR_MATERIAL );
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask ( 1 );
glEnable ( GL_TEXTURE_2D );
// callbacks
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard_func );
glutMouseFunc( mouse_click_func );
glutMotionFunc( mouse_move_func );
glutIdleFunc( idle_func );
glutSetCursor ( GLUT_CURSOR_NONE );
cam_angs.x = 29; cam_angs.y = 75; cam_angs.z = 80.0;
cam_to.x = 0; cam_to.y = 0; cam_to.z = 5;
cam_fov = 35.0;
light[0].x = 39; light[0].y = -60; light[0].z = 43;
light_to[0].x = 0; light_to[0].y = 0; light_to[0].z = 0;
light[1].x = 15; light[1].y = -5; light[1].z = 145;
light_to[1].x = 0; light_to[1].y = 0; light_to[1].z = 0;
light_fov = 45;
#ifdef USE_SHADOWS
createShadowTextures();
createFrameBuffer ();
setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov );
setShadowLightColor ( .7, .7, .7, 0.2, 0.2, 0.2 );
#endif
obj_from.x = 0; obj_from.y = 0; obj_from.z = 20; // emitter
obj_angs.x = 118.7; obj_angs.y = 200; obj_angs.z = 1.0;
obj_dang.x = 1; obj_dang.y = 1; obj_dang.z = 0;
psys.Initialize ( BFLUID, psys_nmax );
psys.SPH_CreateExample ( 0, psys_nmax );
psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) );
psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) );
psys.SetParam ( PNT_DRAWMODE, int(bPntDraw ? 1:0) );
psys.SetParam ( CLR_MODE, iClrMode );
}
int main ( int argc, char **argv )
{
#ifdef BUILD_CUDA
// Initialize CUDA
cudaInit( argc, argv );
#endif
// set up the window
glutInit( &argc, &argv[0] );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowPosition( 100, 100 );
glutInitWindowSize( (int) window_width, (int) window_height );
glutCreateWindow ( "Fluids v.1 (c) 2008, R. Hoetzlein (ZLib)" );
// glutFullScreen ();
// initialize parameters
init();
// wait for something to happen
glutMainLoop();
return 0;
}