Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS

Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
This commit is contained in:
Cyd
2026-06-24 21:28:16 -05:00
commit 2b8ca921cb
66341 changed files with 7923174 additions and 0 deletions
@@ -0,0 +1,125 @@
#ifndef ARRAY_INCLUDED // -*- C++ -*-
#define ARRAY_INCLUDED
#include <memory.h>
//
// Array classes
//
// Taken from gfxTools.h 1.2
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)>(b))?(b):(a))
#endif
template<class T>
class arrayX {
protected:
T *data;
int len;
public:
arrayX() { data=NULL; len=0; }
arrayX(int l) { init(l); }
~arrayX() { free(); }
inline void init(int l);
inline void free();
inline void resize(int l);
inline T& ref(int i);
inline T& operator[](int i) { return data[i]; }
inline T& operator()(int i) { return ref(i); }
inline int length() { return len; }
inline int maxLength() { return len; }
};
template<class T>
inline void arrayX<T>::init(int l)
{
data = new T[l];
len = l;
}
template<class T>
inline void arrayX<T>::free()
{
if( data )
{
delete[] data;
data = NULL;
}
}
template<class T>
inline T& arrayX<T>::ref(int i)
{
#ifdef SAFETY
assert( data );
assert( i>=0 && i<len );
#endif
return data[i];
}
template<class T>
inline void arrayX<T>::resize(int l)
{
T *old = data;
data = new T[l];
data = (T *)memcpy(data,old,MIN(len,l)*sizeof(T));
len = l;
delete[] old;
}
template<class T>
class array2 {
protected:
T *data;
int w, h;
public:
array2() { data=NULL; w=h=0; }
array2(int w, int h) { init(w,h); }
~array2() { free(); }
inline void init(int w, int h);
inline void free();
inline T& ref(int i, int j);
inline T& operator()(int i,int j) { return ref(i,j); }
inline int width() { return w; }
inline int height() { return h; }
};
template<class T>
inline void array2<T>::init(int width,int height)
{
w = width;
h = height;
data = new T[w*h];
}
template<class T>
inline void array2<T>::free()
{
if( data )
{
delete[] data;
data = NULL;
}
}
template<class T>
inline T& array2<T>::ref(int i, int j)
{
#ifdef SAFETY
assert( data );
assert( i>=0 && i<w );
assert( j>=0 && j<h );
#endif
return data[j*w + i];
}
#endif
+165
View File
@@ -0,0 +1,165 @@
#ifndef GEOM_INCLUDED // -*- C++ -*-
#define GEOM_INCLUDED
////////////////////////////////////////////////////////////////////////
//
// Define some basic types and values
//
////////////////////////////////////////////////////////////////////////
#ifdef SAFETY
#include <assert.h>
#endif
typedef double real;
#define EPS 1e-6
#define EPS2 (EPS*EPS)
enum Axis {X, Y, Z, W};
enum Side {Left=-1, On=0, Right=1};
#include <math.h>
#include "Vec2.hpp"
#include "Vec3.hpp"
#ifndef NULL
#define NULL 0
#endif
class Labelled {
public:
unsigned int token;
virtual real redo(void*) { return 1.0f; };
};
////////////////////////////////////////////////////////////////////////
//
// Here we define some useful geometric functions
//
////////////////////////////////////////////////////////////////////////
//
// triArea returns TWICE the area of the oriented triangle ABC.
// The area is positive when ABC is oriented counterclockwise.
inline real triArea(const Vec2& a, const Vec2& b, const Vec2& c)
{
return (b[X] - a[X])*(c[Y] - a[Y]) - (b[Y] - a[Y])*(c[X] - a[X]);
}
inline bool ccw(const Vec2& a, const Vec2& b, const Vec2& c)
{
return triArea(a, b, c) > 0;
}
inline bool rightOf(const Vec2& x, const Vec2& org, const Vec2& dest)
{
return ccw(x, dest, org);
}
inline bool leftOf(const Vec2& x, const Vec2& org, const Vec2& dest)
{
return ccw(x, org, dest);
}
// Returns True if the point d is inside the circle defined by the
// points a, b, c. See Guibas and Stolfi (1985) p.107.
//
inline bool inCircle(const Vec2& a, const Vec2& b, const Vec2& c,
const Vec2& d)
{
return (a[0]*a[0] + a[1]*a[1]) * triArea(b, c, d) -
(b[0]*b[0] + b[1]*b[1]) * triArea(a, c, d) +
(c[0]*c[0] + c[1]*c[1]) * triArea(a, b, d) -
(d[0]*d[0] + d[1]*d[1]) * triArea(a, b, c) > EPS;
}
class PlaneX {
public:
real a, b, c;
PlaneX() { }
PlaneX(const Vec3& p, const Vec3& q, const Vec3& r) { init(p,q,r); }
inline void init(const Vec3& p, const Vec3& q, const Vec3& r);
real operator()(real x,real y) { return a*x + b*y + c; }
real operator()(int x, int y) { return a*x + b*y + c; }
};
inline void PlaneX::init(const Vec3& p, const Vec3& q, const Vec3& r)
// find the plane z=ax+by+c passing through three points p,q,r
{
// We explicitly declare these (rather than putting them in a
// Vector) so that they can be allocated into registers.
real ux = q[X]-p[X], uy = q[Y]-p[Y], uz = q[Z]-p[Z];
real vx = r[X]-p[X], vy = r[Y]-p[Y], vz = r[Z]-p[Z];
real den = ux*vy-uy*vx;
a = (uz*vy - uy*vz)/den;
b = (ux*vz - uz*vx)/den;
c = p[Z] - a*p[X] - b*p[Y];
}
class Line {
private:
real a, b, c;
public:
Line(const Vec2& p, const Vec2& q)
{
Vec2 t = q - p;
real l = t.length();
#ifdef SAFETY
assert(l!=0);
#endif
a = t[Y] / l;
b = - t[X] / l;
c = -(a*p[X] + b*p[Y]);
}
inline real eval(const Vec2& p) const
{
return (a*p[X] + b*p[Y] + c);
}
inline Side classify(const Vec2& p) const
{
real d = eval(p);
if( d < -EPS )
return Left;
else if( d > EPS )
return Right;
else
return On;
}
inline Vec2 intersect(const Line& l) const
{
Vec2 p;
intersect(l, p);
return p;
}
inline void intersect(const Line& l, Vec2& p) const
{
real den = a*l.b - b*l.a;
#ifdef SAFETY
assert(den!=0);
#endif
p[X] = (b*l.c - c*l.b)/den;
p[Y] = (c*l.a - a*l.c)/den;
}
};
#endif
@@ -0,0 +1,437 @@
#include <iostream.h>
#include <assert.h>
#include "GreedyInsert.hpp"
#include "Mask.hpp"
extern ImportMask *MASK;
GreedySubdivision *mesh;
void TrackedTriangle::update(Subdivision& s)
{
GreedySubdivision& gs = (GreedySubdivision&)s;
gs.scanTriangle(*this);
}
real
TrackedTriangle::redo(void *ptr)
{
GreedySubdivision *gs = (GreedySubdivision *)ptr;
return gs->GetDensity(sx, sy);
}
GreedySubdivision::~GreedySubdivision()
{
delete heap;
}
GreedySubdivision::GreedySubdivision(Map *map, real percentage)
{
radius = 12;
radius_method = false;
square_method = true;
bigger_square_method = false;
interest_method = false;
int wish = (int)(4*radius*radius*percentage);
lowPointCount = 2*wish;
highPointCount = 3*wish;
oneOverH_P_Count = 1.0f/(highPointCount-lowPointCount);
wish = (int)(256*256*percentage);
lowPointCount_256 = 2*wish;
highPointCount_256 = 3*wish;
oneOverH_P_Count_256 = 1.0f/(highPointCount_256-lowPointCount_256);
wish = (int)(32*32*percentage);
lowPointCount_32 = 2*wish;
highPointCount_32 = 3*wish;
oneOverH_P_Count_32 = 1.0f/(highPointCount_32-lowPointCount_32);
H = map;
heap = new Heap(128);
int w = H->width;
int h = H->height;
is_used.init(w, h, (unsigned char)DATA_POINT_UNUSED);
are_used_256.init((w>>8)+1, (h>>8)+1);
are_used_32.init((w>>5)+1, (h>>5)+1);
initMesh(Vec2(0,0),
Vec2(0, h-1),
Vec2(w-1, h-1),
Vec2(w-1, 0));
is_used(0, 0) = DATA_POINT_USED;
is_used(0, h-1) = DATA_POINT_USED;
is_used(w-1, h-1) = DATA_POINT_USED;
is_used(w-1, 0) = DATA_POINT_USED;
count = 4;
}
Triangle *GreedySubdivision::allocFace(Edge *e)
{
Triangle *t = new TrackedTriangle(e);
heap->insert(t, -1.0, 1.0f);
return t;
}
void GreedySubdivision::compute_plane(
PlaneX& plane,
Triangle& T,
Map& map
)
{
const Vec2& p1 = T.point1();
const Vec2& p2 = T.point2();
const Vec2& p3 = T.point3();
Vec3 v1(p1, map(p1[X], p1[Y]));
Vec3 v2(p2, map(p2[X], p2[Y]));
Vec3 v3(p3, map(p3[X], p3[Y]));
plane.init(v1, v2, v3);
}
///////////////////////////
//
// This is indeed an ugly hack.
// It should be replaced
//
static int __cdecl vec2_y_compar(const void *a,const void *b)
{
Vec2 &p1=*(Vec2 *)a,
&p2=*(Vec2 *)b;
return (p1[Y]==p2[Y]) ? 0 : (p1[Y] < p2[Y] ? -1 : 1);
}
static void order_triangle_points(Vec2 *by_y,
const Vec2& p1,
const Vec2& p2,
const Vec2& p3)
{
by_y[0] = p1;
by_y[1] = p2;
by_y[2] = p3;
qsort(by_y,3,sizeof(Vec2),vec2_y_compar);
}
void GreedySubdivision::scan_triangle_line(
PlaneX& plane,
int y,
real x1, real x2,
Candidate& candidate
)
{
int startx = (int)ceil(MIN(x1,x2));
int endx = (int)floor(MAX(x1,x2));
if( startx > endx ) return;
real z0 = plane(startx, y);
real dz = plane.a;
real z, diff;
for(int x=startx;x<=endx;x++)
{
if( !is_used(x,y) )
{
z = H->eval(x,y);
diff = fabs(z - z0);
candidate.consider(x, y, MASK->apply(x, y, diff), GetDensity(x, y));
}
z0 += dz;
}
}
void GreedySubdivision::scanTriangle(TrackedTriangle& T)
{
PlaneX z_plane;
compute_plane(z_plane, T, *H);
Vec2 by_y[3];
order_triangle_points(by_y,T.point1(),T.point2(),T.point3());
Vec2& v0 = by_y[0];
Vec2& v1 = by_y[1];
Vec2& v2 = by_y[2];
int y;
int starty, endy;
Candidate candidate;
starty = (int)v0[Y];
endy = (int)v1[Y];
real dx1, dx2, x1, x2;
if(starty != endy && (v2[Y] - v0[Y]) > EPS)
{
dx1 = (v1[X] - v0[X]) / (v1[Y] - v0[Y]);
dx2 = (v2[X] - v0[X]) / (v2[Y] - v0[Y]);
x1 = v0[X];
x2 = v0[X];
for(y=starty;y<endy;y++)
{
scan_triangle_line(z_plane, y, x1, x2, candidate);
x1 += dx1;
x2 += dx2;
}
}
else
{
dx2 = (v2[X] - v0[X]) / (v2[Y] - v0[Y]);
x2 = v0[X];
}
/////////////////////////////
starty = (int)v1[Y];
endy = (int)v2[Y];
if(starty != endy && (v2[Y] - v0[Y]) > EPS)
{
dx1 = (v2[X] - v1[X]) / (v2[Y] - v1[Y]);
x1 = v1[X];
for(y=starty;y<=endy;y++)
{
scan_triangle_line(z_plane, y, x1, x2, candidate);
x1 += dx1;
x2 += dx2;
}
}
/////////////////////////////////
//
// We have now found the appropriate candidate point.
//
if( candidate.import < 1e-4 )
{
if( T.token != NOT_IN_HEAP )
heap->kill(T.token);
#ifdef SAFETY
T.setCandidate(-69, -69, 0.0);
#endif
}
else
{
assert( !is_used(candidate.x, candidate.y) );
T.setCandidate(candidate.x, candidate.y, candidate.import);
if( T.token == NOT_IN_HEAP )
heap->insert(&T, candidate.import, candidate.factor);
else
heap->update(&T, candidate.import, candidate.factor);
}
}
Edge *GreedySubdivision::select(int sx, int sy, Triangle *t)
{
if( is_used(sx, sy) )
{
cerr << " WARNING: Tried to reinsert point: " << sx<<" "<<sy<<endl;
return NULL;
}
is_used(sx, sy) = DATA_POINT_USED;
are_used_256(sx>>8, sy>>8)++;
are_used_32(sx>>5, sy>>5)++;
count++;
return insert(Vec2(sx,sy), t);
}
int GreedySubdivision::greedyInsert()
{
heap_node *node = heap->extract();
if( !node ) return false;
TrackedTriangle &T = *(TrackedTriangle *)node->obj;
int sx, sy;
T.getCandidate(&sx, &sy);
select(sx, sy, &T);
is_used(sx, sy) |= ((int)(heap->GetSize()*0.1f) << 2);
heap->redo(this);
return true;
}
real GreedySubdivision::maxError()
{
heap_node *node = heap->top();
if( !node )
return 0.0;
return node->import;
}
real GreedySubdivision::rmsError()
{
real err = 0.0;
int width = H->width;
int height = H->height;
for(int i=0; i<width; i++)
for(int j=0; j<height; j++)
{
real diff = eval(i, j) - H->eval(i, j);
err += diff * diff;
}
return sqrt(err / (width * height));
}
real GreedySubdivision::eval(int x,int y)
{
Vec2 p(x,y);
Triangle *T = locate(p)->Lface();
PlaneX z_plane;
compute_plane(z_plane, *T, *H);
return z_plane(x,y);
}
int GreedySubdivision::areUsed(int sx, int sy)
{
int i, j, ret = 0;
int w = H->width;
int h = H->height;
int ie = sy+radius<=h?sy+radius:h;
for(i=(sy-radius>=0?sy-radius:0);i<ie;i++)
{
int je = sx+radius<=w?sx+radius:w;
for(j=(sx-radius>=0?sx-radius:0);j<je;j++)
{
const unsigned char *ptr = is_used.GetData(i, j);
ret += (*ptr++) & DATA_POINT_USED;
}
}
return ret;
}
real
GreedySubdivision::GetDensity(int sx, int sy)
{
if(radius_method == true)
{
int density = areUsed(sx, sy);
return (density < lowPointCount ? 1.0f : density > highPointCount ? 0.0f : 1.0f - (density - lowPointCount)*oneOverH_P_Count);
}
real factor = 1.0f;
if( interest_method == true)
{
factor = 0.8f + interest_data(sx, sy)*(0.4f/255.0f);
}
int density_256, density_32;
if(square_method == true)
{
density_256 = are_used_256(sx>>8, sy>>8);
density_32 = are_used_32(sx>>5, sy>>5);
real den_256, den_32;
den_256 = density_256 < lowPointCount_256 ? 1.0f : density_256 > highPointCount_256 ? 0.0f : 1.0f - (density_256 - lowPointCount_256)*oneOverH_P_Count_256;
den_32 = density_32 < lowPointCount_32 ? 1.0f : density_32 > highPointCount_32 ? 0.0f : 1.0f - (density_32 - lowPointCount_32)*oneOverH_P_Count_32;
return factor*(den_32 < den_256 ? den_32 : den_256);
}
else
{
if(bigger_square_method == true)
{
int i, j, px, py, count;
px = sx>>8;
py = sy>>8;
count = 0;
density_256 = 0;
for(j=py-1;j<py+1;j++)
{
for(i=px-1;i<px+1;i++)
{
if(j>=0 && j<are_used_256.height() && i>=0 && i<are_used_256.width())
{
density_256 += are_used_256(i, j);
count++;
}
}
}
density_256 /= count;
px = sx>>5;
py = sy>>5;
count = 0;
density_32 = 0;
for(j=py-1;j<py+1;j++)
{
for(i=px-1;i<px+1;i++)
{
if(j>=0 && j<are_used_32.height() && i>=0 && i<are_used_32.width())
{
density_32 += are_used_32(i, j);
count++;
}
}
}
density_32 /= count;
real den_256, den_32;
den_256 = density_256 < lowPointCount_256 ? 1.0f : density_256 > highPointCount_256 ? 0.0f : 1.0f - (density_256 - lowPointCount_256)*oneOverH_P_Count_256;
den_32 = density_32 < lowPointCount_32 ? 1.0f : density_32 > highPointCount_32 ? 0.0f : 1.0f - (density_32 - lowPointCount_32)*oneOverH_P_Count_32;
return factor*(den_32 < den_256 ? den_32 : den_256);
}
}
return factor;
}
@@ -0,0 +1,158 @@
#ifndef GREEDYINSERT_INCLUDED // -*- C++ -*-
#define GREEDYINSERT_INCLUDED
#include "Heap.hpp"
#include "Subdivision.hpp"
#include "Map.hpp"
class TrackedTriangle : public Triangle
{
//
// candidate position
int sx, sy;
public:
TrackedTriangle(Edge *e, int t=NOT_IN_HEAP)
: Triangle(e, t)
{
}
void update(Subdivision&);
void setCandidate(int x,int y, real) { sx=x; sy=y; }
void getCandidate(int *x, int *y) { *x=sx; *y=sy; }
virtual real redo(void*);
};
class Candidate
{
public:
int x, y;
real import;
real factor;
Candidate() { import = -HUGE; factor = 1.0f; }
void consider(int sx, int sy, real i, real f)
{
if( i*f > import*factor )
{
x = sx;
y = sy;
import = i;
factor = f;
}
}
};
class Array2OfByte {
protected:
int w, h;
unsigned char *data;
public:
Array2OfByte() { data = NULL; w=0; h=0; }
Array2OfByte(int i, int j) { init(i, j); }
~Array2OfByte() { if(data!=NULL) delete [] data; data = NULL; }
void init(int i, int j, unsigned char set=0) { w=i; h=j; data = new unsigned char[w*h]; for(int a=0;a<w*h;a++) data[a] = set; }
void init(int i, int j, unsigned char *d) { w=i; h=j; data = d; }
inline unsigned char& operator()(int i,int j) { return data[j*w+i]; }
inline int width() { return w; }
inline int height() { return h; }
const unsigned char *GetData(int i, int j) { return &data[j*w+i]; }
};
class Array2OfInt {
protected:
int w, h;
int *data;
public:
Array2OfInt() { data = NULL; w=0; h=0; }
Array2OfInt(int i, int j) { init(i, j); }
~Array2OfInt() { if(data!=NULL) delete [] data; data = NULL; }
void init(int i, int j, int set=0) { w=i; h=j; data = new int[w*h]; for(int a=0;a<w*h;a++) data[a] = set; }
void init(int i, int j, int *d) { w=i; h=j; data = d; }
inline int& operator()(int i,int j) { return data[j*w+i]; }
inline int width() { return w; }
inline int height() { return h; }
const int *GetData(int i, int j) { return &data[j*w+i]; }
};
class GreedySubdivision : public Subdivision
{
::Heap *heap;
int count;
protected:
Map *H;
int radius, lowPointCount, highPointCount;
int lowPointCount_256, highPointCount_256;
int lowPointCount_32, highPointCount_32;
real oneOverH_P_Count;
real oneOverH_P_Count_256;
real oneOverH_P_Count_32;
Triangle *allocFace(Edge *e);
void compute_plane(PlaneX&, Triangle&, Map&);
void scan_triangle_line(PlaneX& plane,
int y, real x1, real x2,
Candidate& candidate);
bool radius_method, square_method, bigger_square_method, interest_method;
public:
GreedySubdivision(Map *map, real);
~GreedySubdivision();
Array2OfByte is_used;
Array2OfByte interest_data;
Array2OfInt are_used_256;
Array2OfInt are_used_32;
Edge *select(int sx, int sy, Triangle *t=NULL);
Map& getData() { return *H; }
int areUsed(int sx, int sy);
real GetDensity(int sx, int sy);
void scanTriangle(TrackedTriangle& t);
int greedyInsert();
void SetRadiusMethod(bool b=true) { radius_method = b; }
void SetSquareMethod(bool b=true) { square_method = b; bigger_square_method = !b; }
void SetBiggerSquareMethod(bool b=true) { square_method = !b; bigger_square_method = b; }
void SetInterestMethod(bool b=true) { interest_method = b; }
int pointCount() { return count; }
real maxError();
real rmsError();
real eval(int x,int y);
};
//
// These are the possible values of is_used(x,y):
#define DATA_POINT_UNUSED 0
#define DATA_POINT_USED 1
#define DATA_POINT_IGNORED 2
#define DATA_VALUE_UNKNOWN 3
#endif
+126
View File
@@ -0,0 +1,126 @@
#include <assert.h>
#include <iostream.h>
#include "Heap.hpp"
void Heap::swap(int i,int j)
{
heap_node tmp = ref(i);
ref(i) = ref(j);
ref(j) = tmp;
ref(i).obj->token = i;
ref(j).obj->token = j;
}
void Heap::upheap(int i)
{
if( i==0 ) return;
if( ref(i).import*ref(i).factor > ref(parent(i)).import*ref(parent(i)).factor )
{
swap(i,parent(i));
upheap(parent(i));
}
}
void Heap::downheap(int i)
{
if (i>=size) return; // perhaps just extracted the last
int largest = i,
l = left(i),
r = right(i);
if( l<size && ref(l).import*ref(l).factor > ref(largest).import*ref(largest).factor ) largest = l;
if( r<size && ref(r).import*ref(r).factor > ref(largest).import*ref(largest).factor ) largest = r;
if( largest != i )
{
swap(i,largest);
downheap(largest);
}
}
void Heap::insert(Labelled *t, real v, real f)
{
if( size == maxLength() )
{
cerr << "NOTE: Growing heap from " << size << " to " << 2*size << endl;
resize(2*size);
}
int i = size++;
ref(i).obj = t;
ref(i).import = v;
ref(i).factor = f;
ref(i).obj->token = i;
upheap(i);
}
void Heap::update(Labelled *t, real v, real f)
{
int i = t->token;
if( i >= size )
{
cerr << "WARNING: Attempting to update past end of heap!" << endl;
return;
}
else if( i == NOT_IN_HEAP )
{
cerr << "WARNING: Attempting to update object not in heap!" << endl;
return;
}
real old = ref(i).import;
real oldf = ref(i).factor;
ref(i).import = v;
ref(i).factor = f;
if( v*f<old*oldf )
downheap(i);
else
upheap(i);
}
heap_node *Heap::extract()
{
if( size<1 ) return 0;
swap(0,size-1);
size--;
downheap(0);
ref(size).obj->token = NOT_IN_HEAP;
return &ref(size);
}
heap_node *Heap::kill(int i)
{
if( i>=size )
cerr << "WARNING: Attempt to delete invalid heap node." << endl;
swap(i, size-1);
size--;
ref(size).obj->token = NOT_IN_HEAP;
if( ref(i).import*ref(i).factor < ref(size).import*ref(size).factor )
downheap(i);
else
upheap(i);
return &ref(size);
}
@@ -0,0 +1,65 @@
#ifndef HEAP_INCLUDED // -*- C++ -*-
#define HEAP_INCLUDED
#include "Geom.hpp"
#include "Array.hpp"
#define NOT_IN_HEAP -47
//
//
// This file extracted from ~/anim/lab/mlab
//
//
class heap_node {
public:
real import;
real factor;
Labelled *obj;
heap_node() { obj=NULL; import=0.0; factor = 1.0f; }
heap_node(Labelled *t, double i=0.0) { obj=t; import=i; factor = 1.0f; }
heap_node(const heap_node& h) { import=h.import; obj=h.obj; factor = h.factor; }
void redo(void *ptr) { factor = obj->redo(ptr); }
};
class Heap : public arrayX<heap_node> {
//
// The actual size of the heap. array::length()
// simply returns the amount of allocated space
int size;
void swap(int i, int j);
int parent(int i) { return (i-1)/2; }
int left(int i) { return 2*i+1; }
int right(int i) { return 2*i+2; }
void upheap(int i);
void downheap(int i);
public:
Heap() { size=0; }
Heap(int s) : arrayX<heap_node>(s) { size=0; }
int GetSize() { return size; }
void insert(Labelled *, real, real);
void update(Labelled *, real, real);
void redo(void *ptr) { for(int i=0;i<size;i++) ref(i).redo(ptr); }
heap_node *extract();
heap_node *top() { return size<1 ? (heap_node *)NULL : &ref(0); }
heap_node *kill(int i);
};
#endif
@@ -0,0 +1,30 @@
#include <math.h>
#include "Geom.hpp"
#include "Map.hpp"
Map *DEM;
int point_limit = -1;
real error_threshold = 0.0;
real rint (real in)
{
return floor(in+0.5);
}
void Map::findLimits()
{
min = HUGE;
max = -HUGE;
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
{
real val = eval(i,j);
if( val<min ) min = val;
if( val>max ) max = val;
}
}
+106
View File
@@ -0,0 +1,106 @@
#ifndef MAP_INCLUDED // -*- C++ -*-
#define MAP_INCLUDED
#include <stdlib.h>
#include <iostream.h>
#include "Geom.hpp"
class Map
{
public:
int width;
int height;
int depth; // in bits
real min, max;
real operator()(int i, int j) { return eval(i,j); }
real operator()(real i, real j) { return eval((int)i,(int)j); }
real eval(real i, real j) { return eval((int)i,(int)j); }
virtual real eval(int i, int j) = 0;
virtual void rawRead(istream&) = 0;
virtual void textRead(istream&) = 0;
virtual void *getBlock() { return NULL; }
virtual void findLimits();
};
extern Map *readPGM(istream&);
template<class T>
class DirectMap : public Map
{
T *data;
public:
inline T& ref(int i,int j)
{
#ifdef SAFETY
assert(i>=0); assert(j>=0); assert(i<width); assert(j<height);
#endif
return data[j*width + i];
}
DirectMap(int width, int height);
real eval(int i, int j) { return (real)ref(i,j); }
void *getBlock() { return data; }
void rawRead(istream&);
void textRead(istream&);
};
typedef DirectMap<unsigned char> ByteMap;
typedef DirectMap<unsigned short> ShortMap;
typedef DirectMap<unsigned int> WordMap;
typedef DirectMap<real> RealMap;
template<class T>
DirectMap<T>::DirectMap(int w, int h)
{
width = w;
height = h;
depth = sizeof(T) << 3;
data = (T *)calloc(w*h, sizeof(T));
}
template<class T>
void DirectMap<T>::rawRead(istream& in)
{
char *loc = (char *)data;
int target = width*height*sizeof(T);
while( target>0 )
{
in.read(loc, target);
target -= in.gcount();
loc += in.gcount();
}
}
template<class T>
void DirectMap<T>::textRead(istream& in)
{
for(int j=0;j<height;j++)
for(int i=0;i<width;i++)
{
real val;
in >> val;
ref(i,j) = (T)val;
}
}
#endif
@@ -0,0 +1,61 @@
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "Geom.hpp"
#include "Mask.hpp"
ImportMask *MASK;
RealMask *readMask(istream& in)
{
char magicP, magicNum;
int width, height, maxval;
in >> magicP >> magicNum;
in >> width >> height >> maxval;
if( magicP != 'P' )
{
cerr << "readMask: This is not PGM data." << endl;
return NULL;
}
RealMask *mask = new RealMask(width, height);
if( magicNum == '2' )
{
for(int j=0; j<height; j++)
for(int i=0; i<width; i++)
{
real val;
in >> val;
mask->ref(i, j) = val;
}
}
else if( magicNum == '5' )
{
for(int j=0; j<height; j++)
for(int i=0; i<width; i++)
{
unsigned char val;
in >> val;
mask->ref(i, j) = (real)val;
}
}
else
{
cerr << "readMask: This is not PGM data." << endl;
return NULL;
}
real max = (real)maxval;
for(int i=0; i<width; i++)
for(int j=0; j<height; j++)
mask->ref(i,j) /= max;
return mask;
}
@@ -0,0 +1,47 @@
#ifndef MASK_INCLUDED // -*- C++ -*-
#define MASK_INCLUDED
class ImportMask
{
public:
int width, height;
ImportMask() { width=0; height=0; }
virtual real apply(int /*x*/, int /*y*/, real val) { return val; }
};
class RealMask : public ImportMask
{
real *data;
public:
RealMask(int width, int height);
inline real& ref(int x, int y);
real apply(int x, int y, real val) { return ref(x,y) * val; }
};
inline RealMask::RealMask(int w, int h)
{
width = w;
height = h;
data = (real *)calloc(w*h, sizeof(real));
}
inline real& RealMask::ref(int i, int j)
{
#ifdef SAFETY
assert(i>=0); assert(j>=0); assert(i<width); assert(j<height);
#endif
return data[j*width + i];
}
extern RealMask *readMask(istream&);
#endif
@@ -0,0 +1,82 @@
#include <stdlib.h>
#include <iostream.h>
#include "Quadedge.hpp"
Edge::Edge(const Edge&)
{
cerr << "Edge: Edge assignments are forbidden." << endl;
exit(1);
}
Edge::Edge(Edge *prev)
{
qprev = prev;
prev->qnext = this;
lface = NULL;
token = 0;
}
Edge::Edge()
{
Edge *e0 = this;
Edge *e1 = new Edge(e0);
Edge *e2 = new Edge(e1);
Edge *e3 = new Edge(e2);
qprev = e3;
e3->qnext = e0;
e0->next = e0;
e1->next = e3;
e2->next = e2;
e3->next = e1;
lface = NULL;
token = 0;
}
Edge::~Edge()
{
if( qnext )
{
Edge *e1 = qnext;
Edge *e2 = qnext->qnext;
Edge *e3 = qprev;
#ifdef SAFETY
qnext = NULL;
token = -69;
e1->token = -69;
e2->token = -69;
e3->token = -69;
#endif
e1->qnext = NULL;
e2->qnext = NULL;
e3->qnext = NULL;
delete e1;
delete e2;
delete e3;
}
}
void splice(Edge *a, Edge *b)
{
Edge *alpha = a->Onext()->Rot();
Edge *beta = b->Onext()->Rot();
Edge *t1 = b->Onext();
Edge *t2 = a->Onext();
Edge *t3 = beta->Onext();
Edge *t4 = alpha->Onext();
a->next = t1;
b->next = t2;
alpha->next = t3;
beta->next = t4;
}
@@ -0,0 +1,82 @@
#ifndef QUADEDGE_INCLUDED // -*- C++ -*-
#define QUADEDGE_INCLUDED
#include "Geom.hpp"
class Triangle;
class Edge : public Labelled {
private:
Edge *qnext, *qprev;
Edge(Edge *prev);
protected:
Vec2 *data;
Edge *next;
Triangle *lface;
public:
Edge();
Edge(const Edge&);
~Edge();
//
// Primitive methods
//
Edge *Onext() const { return next; }
Edge *Sym() const { return qnext->qnext; }
Edge *Rot() const { return qnext; }
Edge *invRot() const { return qprev; }
//
// Synthesized methods
//
Edge *Oprev() const { return Rot()->Onext()->Rot(); }
Edge *Dnext() const { return Sym()->Onext()->Sym(); }
Edge *Dprev() const { return invRot()->Onext()->invRot(); }
Edge *Lnext() const { return invRot()->Onext()->Rot(); }
Edge *Lprev() const { return Onext()->Sym(); }
Edge *Rnext() const { return Rot()->Onext()->invRot(); }
Edge *Rprev() const { return Sym()->Onext(); }
Vec2& Org() const { return *data; }
Vec2& Dest() const { return *Sym()->data; }
Triangle *Lface() const { return lface; }
void set_Lface(Triangle *t) { lface = t; }
void EndPoints(Vec2& org, Vec2& dest)
{
data = &org;
Sym()->data = &dest;
}
//
// The fundamental topological operator
friend void splice(Edge *a, Edge *b);
};
inline bool rightOf(const Vec2& x, const Edge *e)
{
return rightOf(x, e->Org(), e->Dest());
}
inline bool leftOf(const Vec2& x, const Edge *e)
{
return leftOf(x, e->Org(), e->Dest());
}
#ifdef IOSTREAMH
inline ostream& operator<<(ostream& out, const Edge *e)
{
return out << "{ " << e->Org() << " ---> " << e->Dest() << " }";
}
#endif
#endif
@@ -0,0 +1,429 @@
#include <stdlib.h>
#include <iostream.h>
#include <assert.h>
#include "Subdivision.hpp"
Edge *Subdivision::makeEdge(Vec2& org, Vec2& dest)
{
Edge *e = new Edge();
e->EndPoints(org, dest);
return e;
}
Edge *Subdivision::makeEdge()
{
return new Edge();
}
void Subdivision::initMesh(const Vec2& A,const Vec2& B,
const Vec2& C,const Vec2& D)
{
Vec2& a = A.clone();
Vec2& b = B.clone();
Vec2& c = C.clone();
Vec2& d = D.clone();
Edge *ea = makeEdge();
ea->EndPoints(a, b);
Edge *eb = makeEdge();
splice(ea->Sym(), eb);
eb->EndPoints(b, c);
Edge *ec = makeEdge();
splice(eb->Sym(), ec);
ec->EndPoints(c, d);
Edge *ed = makeEdge();
splice(ec->Sym(), ed);
ed->EndPoints(d, a);
splice(ed->Sym(), ea);
Edge *diag = makeEdge();
splice(ed->Sym(),diag);
splice(eb->Sym(),diag->Sym());
diag->EndPoints(a,c);
startingEdge = ea;
first_face = NULL;
makeFace(ea->Sym()).update(*this);
makeFace(ec->Sym()).update(*this);
}
void Subdivision::deleteEdge(Edge *e)
{
splice(e, e->Oprev());
splice(e->Sym(), e->Sym()->Oprev());
delete e;
}
Edge *Subdivision::connect(Edge *a, Edge *b)
{
Edge *e = makeEdge();
splice(e, a->Lnext());
splice(e->Sym(), b);
e->EndPoints(a->Dest(), b->Org());
return e;
}
void Subdivision::swap(Edge *e)
{
Triangle *f1 = e->Lface();
Triangle *f2 = e->Sym()->Lface();
Edge *a = e->Oprev();
Edge *b = e->Sym()->Oprev();
splice(e, a);
splice(e->Sym(), b);
splice(e, a->Lnext());
splice(e->Sym(), b->Lnext());
e->EndPoints(a->Dest(), b->Dest());
f1->reshape(e);
f2->reshape(e->Sym());
}
//
// Subdivision iterators
//
static unsigned int timestamp = 0;
static void overEdge(Edge *e, edge_callback fn, void *closure)
{
if( e->token != timestamp )
{
e->token = timestamp;
e->Sym()->token = timestamp;
(*fn)(e, closure);
overEdge(e->Onext(), fn, closure);
overEdge(e->Oprev(), fn, closure);
overEdge(e->Dnext(), fn, closure);
overEdge(e->Dprev(), fn, closure);
}
}
void Subdivision::overEdges(edge_callback fn, void *closure)
{
if( ++timestamp == 0 )
timestamp = 1;
overEdge(startingEdge, fn, closure);
}
void Subdivision::overFaces(face_callback fn, void *closure)
{
Triangle *t = first_face;
while( t )
{
(*fn)(*t, closure);
t = t->getLink();
}
}
//
// Random predicates
//
bool Subdivision::ccwBoundary(const Edge *e)
{
return !rightOf(e->Oprev()->Dest(), e);
}
bool Subdivision::onEdge(const Vec2& x, Edge *e)
{
real t1, t2, t3;
t1 = (x - e->Org()).length();
t2 = (x - e->Dest()).length();
if (t1 < EPS || t2 < EPS)
return true;
t3 = (e->Org() - e->Dest()).length();
if (t1 > t3 || t2 > t3)
return false;
Line line(e->Org(), e->Dest());
return (fabs(line.eval(x)) < EPS);
}
bool Subdivision::isInterior(Edge *e)
//
// Tests whether e is an interior edge.
//
// WARNING: This topological test will not work if the boundary is
// a triangle. This is not a problem here; the boundary is
// always a rectangle. But if you try to adapt this code, please
// keep this in mind.
{
return (e->Lnext()->Lnext()->Lnext() == e &&
e->Rnext()->Rnext()->Rnext() == e );
}
bool Subdivision::shouldSwap(const Vec2& x, Edge *e)
{
Edge *t = e->Oprev();
return inCircle(e->Org(), t->Dest(), e->Dest(), x);
}
Edge *Subdivision::locate(const Vec2& x, Edge *start)
{
Edge *e = start;
real t = triArea(x, e->Dest(), e->Org());
if (t>0) { // x is to the right of edge e
t = -t;
e = e->Sym();
}
while (true)
{
Edge *eo = e->Onext();
Edge *ed = e->Dprev();
real to = triArea(x, eo->Dest(), eo->Org());
real td = triArea(x, ed->Dest(), ed->Org());
if (td>0) // x is below ed
if (to>0 || to==0 && t==0) {// x is interior, or origin endpoint
startingEdge = e;
return e;
}
else { // x is below ed, below eo
t = to;
e = eo;
}
else // x is on or above ed
if (to>0) // x is above eo
if (td==0 && t==0) { // x is destination endpoint
startingEdge = e;
return e;
}
else { // x is on or above ed and above eo
t = td;
e = ed;
}
else // x is on or below eo
if (t==0 && !leftOf(eo->Dest(), e))
// x on e but subdiv. is to right
e = e->Sym();
else if (rand()&1) { // x is on or above ed and
t = to; // on or below eo; step randomly
e = eo;
}
else {
t = td;
e = ed;
}
}
}
Edge *Subdivision::spoke(Vec2& x, Edge *e)
{
Triangle *new_faces[4];
int facedex = 0;
//
// NOTE: e is the edge returned by locate(x)
//
if ( (x == e->Org()) || (x == e->Dest()) ) {
// point is already in the mesh
//
/*
cerr << "WARNING: Tried to reinsert point: " << x << endl;
cerr << " org: " << e->Org() << endl;
cerr << " dest: " << e->Dest() << endl;
*/
return NULL;
}
Edge *boundary_edge = NULL;
Triangle *lface = e->Lface();
lface->dontAnchor(e);
new_faces[facedex++] = lface;
if( onEdge(x,e) )
{
if( ccwBoundary(e) ) {
//
// e lies on the boundary
// Defer deletion until after new edges are added.
boundary_edge = e;
}
else {
Triangle *sym_lface = e->Sym()->Lface();
new_faces[facedex++] = sym_lface;
sym_lface->dontAnchor(e->Sym());
e = e->Oprev();
deleteEdge(e->Onext());
}
}
else
{
// x lies within the Lface of e
}
Edge *base = makeEdge(e->Org(), x.clone());
splice(base, e);
startingEdge = base;
do {
base = connect(e, base->Sym());
e = base->Oprev();
} while( e->Lnext() != startingEdge );
if( boundary_edge )
deleteEdge(boundary_edge);
// Update all the faces in our new spoked polygon.
// If point x on perimeter, then don't add an exterior face
base = boundary_edge ? startingEdge->Rprev() : startingEdge->Sym();
do {
if( facedex )
new_faces[--facedex]->reshape(base);
else
makeFace(base);
base = base->Onext();
} while( base != startingEdge->Sym() );
return startingEdge;
}
//
// s is a spoke pointing OUT from x
//
void Subdivision::optimize(Vec2& x, Edge *s)
{
Edge *start_spoke = s;
Edge *spoke = s;
do {
Edge *e = spoke->Lnext();
Edge *t = e->Oprev();
if( isInterior(e) && shouldSwap(x, e) )
swap(e);
else
{
spoke = spoke->Onext();
if( spoke == start_spoke )
break;
}
} while( true );
//
// Now, update all the triangles
spoke = start_spoke;
do {
Edge *e = spoke->Lnext();
Triangle *t = e->Lface();
if( t ) t->update(*this);
spoke = spoke->Onext();
} while( spoke != start_spoke );
}
Edge *Subdivision::insert(Vec2& x, Triangle *tri)
{
Edge *e = tri?locate(x, tri->getAnchor()):locate(x);
Edge *start_spoke = spoke(x, e);
if( start_spoke )
optimize(x, start_spoke->Sym());
return start_spoke;
}
Triangle *Subdivision::allocFace(Edge *e)
{
return new Triangle(e);
}
Triangle& Subdivision::makeFace(Edge *e)
{
Triangle *t = allocFace(e);
first_face = t->linkTo(first_face);
return *t;
}
void Triangle::dontAnchor(Edge *e)
{
if( anchor == e )
{
anchor = e->Lnext();
}
}
void Triangle::reshape(Edge *e)
{
anchor = e;
e->set_Lface(this);
e->Lnext()->set_Lface(this);
e->Lprev()->set_Lface(this);
}
void Triangle::update(Subdivision&)
// called by reshape to update stuff
//
// the default method will do nothing
{
}
@@ -0,0 +1,95 @@
#ifndef SUBDIVISION_INCLUDED // -*- C++ -*-
#define SUBDIVISION_INCLUDED
#include "Quadedge.hpp"
class Subdivision;
class Triangle : public Labelled {
Edge *anchor;
Triangle *next_face;
public:
Triangle(Edge *e, int t=0)
{
token = t;
reshape(e);
}
Triangle *linkTo(Triangle *t) { next_face = t; return this; }
Triangle *getLink() { return next_face; }
Edge *getAnchor() { return anchor; }
void dontAnchor(Edge *e);
void reshape(Edge *e);
virtual void update(Subdivision&); // called to update stuff
const Vec2& point1() const { return anchor->Org(); }
const Vec2& point2() const { return anchor->Dest(); }
const Vec2& point3() const { return anchor->Lprev()->Org(); }
};
typedef void (*edge_callback)(Edge *, void *);
typedef void (*face_callback)(Triangle&, void *);
class Subdivision {
private:
Edge *startingEdge;
Triangle *first_face;
protected:
void initMesh(const Vec2&, const Vec2&, const Vec2&, const Vec2&);
Subdivision() { }
Edge *makeEdge();
Edge *makeEdge(Vec2& org, Vec2& dest);
virtual Triangle *allocFace(Edge *e);
Triangle& makeFace(Edge *e);
void deleteEdge(Edge *);
Edge *connect(Edge *a, Edge *b);
void swap(Edge *e);
//
// Some random functions
bool ccwBoundary(const Edge *e);
bool onEdge(const Vec2&, Edge *);
public:
Subdivision(Vec2& a, Vec2& b, Vec2& c, Vec2& d) { initMesh(a,b,c,d); }
//
// virtual functions for customization
virtual bool shouldSwap(const Vec2&, Edge *);
bool isInterior(Edge *);
Edge *spoke(Vec2&, Edge *e);
void optimize(Vec2&, Edge *);
Edge *locate(const Vec2& x) { return locate(x, startingEdge); }
Edge *locate(const Vec2&, Edge *hint);
Edge *insert(Vec2&, Triangle *t=NULL);
void overEdges(edge_callback, void *closure=NULL);
void overFaces(face_callback, void *closure=NULL);
};
#ifdef IOSTREAMH
inline ostream& operator<<(ostream& out, Triangle& t)
{
return out << "Triangle("<< t.point1() << " " << t.point2() << " "
<< t.point3() << ")";
}
#endif
#endif
@@ -0,0 +1,216 @@
# Microsoft Developer Studio Project File - Name="Terra" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=Terra - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Terra.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Terra.mak" CFG="Terra - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Terra - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "Terra - Win32 Profile" (based on "Win32 (x86) Static Library")
!MESSAGE "Terra - Win32 Armor" (based on "Win32 (x86) Static Library")
!MESSAGE "Terra - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "Terra - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /G6 /Zp4 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Terra - Win32 Profile"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Profile"
# PROP BASE Intermediate_Dir "Profile"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Profile"
# PROP Intermediate_Dir "Profile"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /G6 /Zp4 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Terra - Win32 Armor"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Armor"
# PROP BASE Intermediate_Dir "Armor"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Armor"
# PROP Intermediate_Dir "Armor"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /G6 /Zp4 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Terra - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /Zp4 /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "Terra - Win32 Release"
# Name "Terra - Win32 Profile"
# Name "Terra - Win32 Armor"
# Name "Terra - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\greedy.cpp
# End Source File
# Begin Source File
SOURCE=.\GreedyInsert.cpp
# End Source File
# Begin Source File
SOURCE=.\Heap.cpp
# End Source File
# Begin Source File
SOURCE=.\Map.cpp
# End Source File
# Begin Source File
SOURCE=.\Mask.cpp
# End Source File
# Begin Source File
SOURCE=.\Quadedge.cpp
# End Source File
# Begin Source File
SOURCE=.\Subdivision.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\Array.hpp
# End Source File
# Begin Source File
SOURCE=.\Geom.hpp
# End Source File
# Begin Source File
SOURCE=.\GreedyInsert.hpp
# End Source File
# Begin Source File
SOURCE=.\Heap.hpp
# End Source File
# Begin Source File
SOURCE=.\Map.hpp
# End Source File
# Begin Source File
SOURCE=.\Mask.hpp
# End Source File
# Begin Source File
SOURCE=.\Quadedge.hpp
# End Source File
# Begin Source File
SOURCE=.\Subdivision.hpp
# End Source File
# Begin Source File
SOURCE=.\terra.hpp
# End Source File
# Begin Source File
SOURCE=.\Vec2.hpp
# End Source File
# Begin Source File
SOURCE=.\Vec3.hpp
# End Source File
# End Group
# End Target
# End Project
+158
View File
@@ -0,0 +1,158 @@
#ifndef VEC2_INCLUDED // -*- C++ -*-
#define VEC2_INCLUDED
class Vec2 {
protected:
real elt[2];
inline void copy(const Vec2& v);
public:
// Standard constructors
Vec2(real x=0, real y=0) { elt[0]=x; elt[1]=y; }
Vec2(const Vec2& v) { copy(v); }
Vec2(const real *v) { elt[0]=v[0]; elt[1]=v[1]; }
Vec2& clone() const { return *(new Vec2(elt[0], elt[1])); }
// Access methods
real& operator()(int i) { return elt[i]; }
const real& operator()(int i) const { return elt[i]; }
real& operator[](int i) { return elt[i]; }
const real& operator[](int i) const { return elt[i]; }
// Assignment methods
inline Vec2& operator=(const Vec2& v);
inline Vec2& operator+=(const Vec2& v);
inline Vec2& operator-=(const Vec2& v);
inline Vec2& operator*=(real s);
inline Vec2& operator/=(real s);
// Arithmetic methods
inline Vec2 operator+(const Vec2& v) const;
inline Vec2 operator-(const Vec2& v) const;
inline Vec2 operator-() const;
inline Vec2 operator*(real s) const;
inline Vec2 operator/(real s) const;
inline real operator*(const Vec2& v) const;
#ifdef IOSTREAMH
// Input/Output methods
friend ostream& operator<<(ostream&, const Vec2&);
friend istream& operator>>(istream&, Vec2&);
#endif
// Additional vector methods
inline real length();
inline real norm();
inline real norm2();
inline real unitize();
inline int operator==(const Vec2& v) const
{
return (*this - v).norm2() < EPS2;
}
};
inline void Vec2::copy(const Vec2& v)
{
elt[0]=v.elt[0]; elt[1]=v.elt[1];
}
inline Vec2& Vec2::operator=(const Vec2& v)
{
copy(v);
return *this;
}
inline Vec2& Vec2::operator+=(const Vec2& v)
{
elt[0] += v[0];
elt[1] += v[1];
return *this;
}
inline Vec2& Vec2::operator-=(const Vec2& v)
{
elt[0] -= v[0];
elt[1] -= v[1];
return *this;
}
inline Vec2& Vec2::operator*=(real s)
{
elt[0] *= s;
elt[1] *= s;
return *this;
}
inline Vec2& Vec2::operator/=(real s)
{
elt[0] /= s;
elt[1] /= s;
return *this;
}
///////////////////////
inline Vec2 Vec2::operator+(const Vec2& v) const
{
Vec2 w(elt[0]+v[0], elt[1]+v[1]);
return w;
}
inline Vec2 Vec2::operator-(const Vec2& v) const
{
Vec2 w(elt[0]-v[0], elt[1]-v[1]);
return w;
}
inline Vec2 Vec2::operator-() const
{
return Vec2(-elt[0], -elt[1]);
}
inline Vec2 Vec2::operator*(real s) const
{
Vec2 w(elt[0]*s, elt[1]*s);
return w;
}
inline Vec2 Vec2::operator/(real s) const
{
Vec2 w(elt[0]/s, elt[1]/s);
return w;
}
inline real Vec2::operator*(const Vec2& v) const
{
return elt[0]*v[0] + elt[1]*v[1];
}
inline real Vec2::length()
{
return norm();
}
inline real Vec2::norm()
{
return sqrt(elt[0]*elt[0] + elt[1]*elt[1]);
}
inline real Vec2::norm2()
{
return elt[0]*elt[0] + elt[1]*elt[1];
}
inline real Vec2::unitize()
{
real l=norm();
if( l!=1.0 )
(*this)/=l;
return l;
}
#endif
+161
View File
@@ -0,0 +1,161 @@
#ifndef VEC3_INCLUDED // -*- C++ -*-
#define VEC3_INCLUDED
class Vec3 {
protected:
real elt[3];
inline void copy(const Vec3& v);
public:
// Standard constructors
Vec3(real x=0, real y=0, real z=0) { elt[0]=x; elt[1]=y; elt[2]=z; }
Vec3(const Vec2& v, real z) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=z; }
Vec3(const Vec3& v) { copy(v); }
Vec3(const real *v) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=v[2]; }
// Access methods
real& operator()(int i) { return elt[i]; }
const real& operator()(int i) const { return elt[i]; }
real& operator[](int i) { return elt[i]; }
const real& operator[](int i) const { return elt[i]; }
// Assignment methods
inline Vec3& operator=(const Vec3& v);
inline Vec3& operator+=(const Vec3& v);
inline Vec3& operator-=(const Vec3& v);
inline Vec3& operator*=(real s);
inline Vec3& operator/=(real s);
// Arithmetic methods
inline Vec3 operator+(const Vec3& v) const;
inline Vec3 operator-(const Vec3& v) const;
inline Vec3 operator-() const;
inline Vec3 operator*(real s) const;
inline Vec3 operator/(real s) const;
inline real operator*(const Vec3& v) const;
inline Vec3 operator^(const Vec3& v) const;
// Additional vector methods
inline real length();
inline real norm();
inline real norm2();
inline real unitize();
};
inline void Vec3::copy(const Vec3& v)
{
elt[0]=v.elt[0]; elt[1]=v.elt[1]; elt[2]=v.elt[2];
}
inline Vec3& Vec3::operator=(const Vec3& v)
{
copy(v);
return *this;
}
inline Vec3& Vec3::operator+=(const Vec3& v)
{
elt[0] += v[0];
elt[1] += v[1];
elt[2] += v[2];
return *this;
}
inline Vec3& Vec3::operator-=(const Vec3& v)
{
elt[0] -= v[0];
elt[1] -= v[1];
elt[2] -= v[2];
return *this;
}
inline Vec3& Vec3::operator*=(real s)
{
elt[0] *= s;
elt[1] *= s;
elt[2] *= s;
return *this;
}
inline Vec3& Vec3::operator/=(real s)
{
elt[0] /= s;
elt[1] /= s;
elt[2] /= s;
return *this;
}
///////////////////////
inline Vec3 Vec3::operator+(const Vec3& v) const
{
Vec3 w(elt[0]+v[0], elt[1]+v[1], elt[2]+v[2]);
return w;
}
inline Vec3 Vec3::operator-(const Vec3& v) const
{
Vec3 w(elt[0]-v[0], elt[1]-v[1], elt[2]-v[2]);
return w;
}
inline Vec3 Vec3::operator-() const
{
return Vec3(-elt[0], -elt[1], -elt[2]);
}
inline Vec3 Vec3::operator*(real s) const
{
Vec3 w(elt[0]*s, elt[1]*s, elt[2]*s);
return w;
}
inline Vec3 Vec3::operator/(real s) const
{
Vec3 w(elt[0]/s, elt[1]/s, elt[2]/s);
return w;
}
inline real Vec3::operator*(const Vec3& v) const
{
return elt[0]*v[0] + elt[1]*v[1] + elt[2]*v[2];
}
inline Vec3 Vec3::operator^(const Vec3& v) const
{
Vec3 w( elt[1]*v[2] - v[1]*elt[2],
-elt[0]*v[2] + v[0]*elt[2],
elt[0]*v[1] - v[0]*elt[1] );
return w;
}
inline real Vec3::length()
{
return norm();
}
inline real Vec3::norm()
{
return sqrt(elt[0]*elt[0] + elt[1]*elt[1] + elt[2]*elt[2]);
}
inline real Vec3::norm2()
{
return elt[0]*elt[0] + elt[1]*elt[1] + elt[2]*elt[2];
}
inline real Vec3::unitize()
{
real l=norm();
if( l!=1.0 )
(*this)/=l;
return l;
}
#endif
@@ -0,0 +1,105 @@
#include "terra.hpp"
void scripted_preinsertion(istream& script)
{
char op[4];
int x, y;
while( script.peek() != EOF )
{
script >> op >> x >> y;
switch( op[0] )
{
case 's':
if( !mesh->is_used(x, y) )
{
mesh->select(x, y);
mesh->is_used(x, y) = DATA_POINT_USED;
}
break;
case 'i':
if( !mesh->is_used(x,y) )
mesh->is_used(x, y) = DATA_POINT_IGNORED;
break;
case 'u':
if( !mesh->is_used(x,y) )
mesh->is_used(x, y) = DATA_VALUE_UNKNOWN;
break;
default:
break;
}
}
}
void subsample_insertion(int target_width)
{
int width = DEM->width;
int height = DEM->height;
// 'i' is the target width and 'j' is the target height
real i = (real)target_width;
real j = (i*height) / width;
real dx = (width-1)/(i-1);
real dy = (height-1)/(j-1);
real u, v;
int x, y;
for(u=0; u<i; u++)
for(v=0; v<j; v++)
{
x = (int)rint(u*dx);
y = (int)rint(v*dy);
if( !mesh->is_used(x,y) )
mesh->select(x, y);
}
}
inline int goal_not_met()
{
return mesh->maxError() > error_threshold &&
mesh->pointCount() < point_limit;
}
static void announce_goal()
{
cerr << "Goal conditions met:" << endl;
cerr << " error=" << mesh->maxError()
<< " [thresh="<< error_threshold << "]" << endl;
cerr << " points=" << mesh->pointCount()
<< " [limit=" << point_limit << "]" << endl;
}
void greedy_insertion()
{
while( goal_not_met() )
{
if( !mesh->greedyInsert() )
break;
}
announce_goal();
}
void display_greedy_insertion(void (*callback)())
{
while( goal_not_met() )
{
if( !mesh->greedyInsert() )
{
(*callback)();
break;
}
(*callback)();
}
announce_goal();
}
@@ -0,0 +1,33 @@
#ifndef TERRA_INCLUDED // -*- C++ -*-
#define TERRA_INCLUDED
#include "GreedyInsert.hpp"
#include "Map.hpp"
#include "Mask.hpp"
extern GreedySubdivision *mesh;
extern Map *DEM;
extern ImportMask *MASK;
extern real error_threshold;
extern int point_limit;
extern real height_scale;
enum FileFormat {NULLfile, TINfile, EPSfile, DEMfile, OBJfile, RMSfile};
extern FileFormat output_format;
extern char *output_filename;
extern char *script_filename;
extern int goal_not_met();
extern void greedy_insertion();
extern void display_greedy_insertion(void (*callback)());
extern void subsample_insertion(int target_width);
extern void generate_output(char *filename=NULL,
FileFormat format=NULLfile);
extern void process_cmdline(int argc, char **argv);
extern double rint (double);
#endif