This commit was generated by cvs2svn to compensate for changes in r4,

which included commits to RCS files with non-trunk default branches.
pull/3/head
Chris Laurel 2001-02-26 09:56:35 +00:00
commit b6f1c72ae5
92 changed files with 17972 additions and 0 deletions

58
src/3dschunk.h 100644
View File

@ -0,0 +1,58 @@
// 3dschunk.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _3DSCHUNK_H_
#define _3DSCHUNK_H_
enum M3DChunkType
{
M3DCHUNK_NULL = 0x0000,
M3DCHUNK_VERSION = 0x0002,
M3DCHUNK_COLOR_FLOAT = 0x0010,
M3DCHUNK_COLOR_24 = 0x0011,
M3DCHUNK_LIN_COLOR_F = 0x0013,
M3DCHUNK_INT_PERCENTAGE = 0x0030,
M3DCHUNK_FLOAT_PERCENTAGE = 0x0031,
M3DCHUNK_MASTER_SCALE = 0x0100,
M3DCHUNK_BACKGROUND_COLOR = 0x1200,
M3DCHUNK_MESHDATA = 0x3d3d,
M3DCHUNK_MESH_VERSION = 0x3d3e,
M3DCHUNK_NAMED_OBJECT = 0x4000,
M3DCHUNK_TRIANGLE_MESH = 0x4100,
M3DCHUNK_POINT_ARRAY = 0x4110,
M3DCHUNK_POINT_FLAG_ARRAY = 0x4111,
M3DCHUNK_FACE_ARRAY = 0x4120,
M3DCHUNK_MESH_MATERIAL_GROUP = 0x4130,
M3DCHUNK_MESH_TEXTURE_COORDS = 0x4140,
M3DCHUNK_MESH_SMOOTH_GROUP = 0x4150,
M3DCHUNK_MESH_MATRIX = 0x4160,
M3DCHUNK_MAGIC = 0x4d4d,
M3DCHUNK_MATERIAL_NAME = 0xa000,
M3DCHUNK_MATERIAL_AMBIENT = 0xa010,
M3DCHUNK_MATERIAL_DIFFUSE = 0xa020,
M3DCHUNK_MATERIAL_SPECULAR = 0xa030,
M3DCHUNK_MATERIAL_SHININESS = 0xa040,
M3DCHUNK_MATERIAL_SHIN2PCT = 0xa041,
M3DCHUNK_MATERIAL_TRANSPARENCY = 0xa050,
M3DCHUNK_MATERIAL_XPFALL = 0xa052,
M3DCHUNK_MATERIAL_REFBLUR = 0xa053,
M3DCHUNK_MATERIAL_SELF_ILLUM = 0xa084,
M3DCHUNK_MATERIAL_WIRESIZE = 0xa087,
M3DCHUNK_MATERIAL_XPFALLIN = 0xa08a,
M3DCHUNK_MATERIAL_SHADING = 0xa100,
M3DCHUNK_MATERIAL_ENTRY = 0xafff,
M3DCHUNK_KFDATA = 0xb000,
};
#endif // _3DSCHUNK_H_

245
src/3dsmesh.cpp 100644
View File

@ -0,0 +1,245 @@
// 3dsmesh.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "gl.h"
#include "3dsmesh.h"
using namespace std;
static TriangleList* convertTriangleMesh(M3DTriangleMesh& mesh,
const M3DScene& scene);
Mesh3DS::Mesh3DS(const M3DScene& scene)
{
for (int i = 0; i < scene.getModelCount(); i++)
{
M3DModel* model = scene.getModel(i);
if (model != NULL)
{
for (int j = 0; j < model->getTriMeshCount(); j++)
{
M3DTriangleMesh* mesh = model->getTriMesh(j);
if (mesh != NULL)
{
triLists.insert(triLists.end(),
convertTriangleMesh(*mesh, scene));
}
}
}
}
}
Mesh3DS::~Mesh3DS()
{
for (TriListVec::iterator i = triLists.begin(); i != triLists.end(); i++)
if (*i != NULL)
delete *i;
}
void Mesh3DS::render()
{
for (TriListVec::iterator i = triLists.begin(); i != triLists.end(); i++)
(*i)->render();
}
void Mesh3DS::normalize()
{
AxisAlignedBox bbox;
for (TriListVec::iterator i = triLists.begin(); i != triLists.end(); i++)
bbox.include((*i)->getBoundingBox());
Point3f center = bbox.getCenter();
Vec3f extents = bbox.getExtents();
float maxExtent = extents.x;
if (extents.y > maxExtent)
maxExtent = extents.y;
if (extents.z > maxExtent)
maxExtent = extents.z;
printf("Normalize: %f\n", maxExtent);
for (i = triLists.begin(); i != triLists.end(); i++)
(*i)->transform(Point3f(0, 0, 0) - center, 1.0f / maxExtent);
}
static TriangleList* convertTriangleMesh(M3DTriangleMesh& mesh,
const M3DScene& scene)
{
TriangleList* tl = new TriangleList();
int nFaces = mesh.getFaceCount();
int nVertices = mesh.getVertexCount();
bool smooth = (mesh.getSmoothingGroupCount() == nFaces);
int i;
Vec3f* faceNormals = new Vec3f[nFaces];
Vec3f* vertexNormals = new Vec3f[nFaces * 3];
int* faceCounts = new int[nVertices];
int** vertexFaces = new int*[nVertices];
for (i = 0; i < nVertices; i++)
{
faceCounts[i] = 0;
vertexFaces[i] = NULL;
}
// generate face normals
for (i = 0; i < nFaces; i++)
{
uint16 v0, v1, v2;
mesh.getFace(i, v0, v1, v2);
faceCounts[v0]++;
faceCounts[v1]++;
faceCounts[v2]++;
Point3f p0 = mesh.getVertex(v0);
Point3f p1 = mesh.getVertex(v1);
Point3f p2 = mesh.getVertex(v2);
faceNormals[i] = cross(p1 - p0, p2 - p1);
faceNormals[i].normalize();
}
if (!smooth && 0)
{
for (i = 0; i < nFaces; i++)
{
vertexNormals[i * 3] = faceNormals[i];
vertexNormals[i * 3 + 1] = faceNormals[i];
vertexNormals[i * 3 + 2] = faceNormals[i];
}
}
else
{
// allocate space for vertex face indices
for (i = 0; i < nVertices; i++)
{
vertexFaces[i] = new int[faceCounts[i] + 1];
vertexFaces[i][0] = faceCounts[i];
}
for (i = 0; i < nFaces; i++)
{
uint16 v0, v1, v2;
mesh.getFace(i, v0, v1, v2);
vertexFaces[v0][faceCounts[v0]--] = i;
vertexFaces[v1][faceCounts[v1]--] = i;
vertexFaces[v2][faceCounts[v2]--] = i;
}
#if 0
for (i = 0; i < nVertices; i++)
{
printf("%d: ", i);
for (int j = 1; j < vertexFaces[i][0]; j++)
{
printf("%d ", vertexFaces[i][j]);
}
printf("\n");
}
#endif
// average face normals to compute the vertex normals
for (i = 0; i < nFaces; i++)
{
uint16 v0, v1, v2;
mesh.getFace(i, v0, v1, v2);
uint32 smoothingGroups = mesh.getSmoothingGroups(i);
int j;
Vec3f v = Vec3f(0, 0, 0);
for (j = 1; j <= vertexFaces[v0][0]; j++)
{
int k = vertexFaces[v0][j];
// if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
if (faceNormals[i] * faceNormals[k] > 0.5f)
v += faceNormals[k];
}
v.normalize();
vertexNormals[i * 3] = v;
v = Vec3f(0, 0, 0);
for (j = 1; j <= vertexFaces[v1][0]; j++)
{
int k = vertexFaces[v1][j];
// if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
if (faceNormals[i] * faceNormals[k] > 0.5f)
v += faceNormals[k];
}
v.normalize();
vertexNormals[i * 3 + 1] = v;
v = Vec3f(0, 0, 0);
for (j = 1; j <= vertexFaces[v2][0]; j++)
{
int k = vertexFaces[v2][j];
// if (k == i || (smoothingGroups & mesh.getSmoothingGroups(k)) != 0)
if (faceNormals[i] * faceNormals[k] > 0.5f)
v += faceNormals[k];
}
v.normalize();
vertexNormals[i * 3 + 2] = v;
}
}
// build the triangle list
for (i = 0; i < nFaces; i++)
{
uint16 v0, v1, v2;
mesh.getFace(i, v0, v1, v2);
tl->addTriangle(mesh.getVertex(v0), vertexNormals[i * 3],
mesh.getVertex(v1), vertexNormals[i * 3 + 1],
mesh.getVertex(v2), vertexNormals[i * 3 + 2]);
}
// set the color
{
string materialName = mesh.getMaterialName();
if (materialName.length() > 0)
{
tl->setColorMode(1);
int nMaterials = scene.getMaterialCount();
for (i = 0; i < nMaterials; i++)
{
M3DMaterial* material = scene.getMaterial(i);
if (materialName == material->getName())
{
M3DColor diffuse = material->getDiffuseColor();
tl->setColor(Vec3f(diffuse.red, diffuse.green, diffuse.blue));
break;
}
}
}
}
// clean up
if (faceNormals != NULL)
delete[] faceNormals;
if (vertexNormals != NULL)
delete[] vertexNormals;
if (faceCounts != NULL)
delete[] faceCounts;
if (vertexFaces != NULL)
{
for (i = 0; i < nVertices; i++)
{
if (vertexFaces[i] != NULL)
delete[] vertexFaces[i];
}
delete[] vertexFaces;
}
return tl;
}

33
src/3dsmesh.h 100644
View File

@ -0,0 +1,33 @@
// 3dsmesh.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _3DSMESH_H_
#define _3DSMESH_H_
#include <vector>
#include "mesh.h"
#include "trilist.h"
#include "3dsmodel.h"
class Mesh3DS : public Mesh
{
public:
Mesh3DS(const M3DScene& scene);
~Mesh3DS();
void render();
void normalize();
private:
typedef std::vector<TriangleList*> TriListVec;
TriListVec triLists;
};
#endif // _3DSMESH_H_

257
src/3dsmodel.cpp 100644
View File

@ -0,0 +1,257 @@
// 3dsmodel.cpp
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "3dsmodel.h"
using namespace std;
M3DColor::M3DColor() :
red(0), green(0), blue(0)
{
}
M3DColor::M3DColor(float _red, float _green, float _blue) :
red(_red), green(_green), blue(_blue)
{
}
M3DMaterial::M3DMaterial() :
ambient(0, 0, 0),
diffuse(0, 0, 0),
specular(0, 0, 0)
{
}
string M3DMaterial::getName() const
{
return name;
}
void M3DMaterial::setName(string _name)
{
name = _name;
}
M3DColor M3DMaterial::getDiffuseColor() const
{
return diffuse;
}
void M3DMaterial::setDiffuseColor(M3DColor color)
{
diffuse = color;
}
M3DColor M3DMaterial::getAmbientColor() const
{
return ambient;
}
void M3DMaterial::setAmbientColor(M3DColor color)
{
ambient = color;
}
M3DColor M3DMaterial::getSpecularColor() const
{
return specular;
}
void M3DMaterial::setSpecularColor(M3DColor color)
{
specular = color;
}
M3DTriangleMesh::M3DTriangleMesh()
{
matrix = Mat4f::identity();
}
M3DTriangleMesh::~M3DTriangleMesh()
{
}
Mat4f M3DTriangleMesh::getMatrix() const
{
return matrix;
}
void M3DTriangleMesh::setMatrix(const Mat4f& m)
{
matrix = m;
}
Point3f M3DTriangleMesh::getVertex(uint16 n) const
{
return points[n];
}
uint16 M3DTriangleMesh::getVertexCount() const
{
return (uint16) (points.size());
}
void M3DTriangleMesh::addVertex(Point3f p)
{
points.insert(points.end(), p);
}
void M3DTriangleMesh::getFace(uint16 n, uint16& v0, uint16& v1, uint16& v2) const
{
int m = (int) n * 3;
v0 = faces[m];
v1 = faces[m + 1];
v2 = faces[m + 2];
}
uint16 M3DTriangleMesh::getFaceCount() const
{
return (uint16) (faces.size() / 3);
}
void M3DTriangleMesh::addFace(uint16 v0, uint16 v1, uint16 v2)
{
faces.insert(faces.end(), v0);
faces.insert(faces.end(), v1);
faces.insert(faces.end(), v2);
}
uint32 M3DTriangleMesh::getSmoothingGroups(uint16 face) const
{
if (face < smoothingGroups.size())
return smoothingGroups[face];
else
return 0;
}
void M3DTriangleMesh::addSmoothingGroups(uint32 smGroups)
{
smoothingGroups.insert(smoothingGroups.end(), smGroups);
}
uint16 M3DTriangleMesh::getSmoothingGroupCount() const
{
return (uint16) (smoothingGroups.size());
}
string M3DTriangleMesh::getMaterialName() const
{
return materialName;
}
void M3DTriangleMesh::setMaterialName(string _materialName)
{
materialName = _materialName;
}
M3DModel::M3DModel()
{
}
M3DModel::~M3DModel()
{
for (int i = 0; i < triMeshes.size(); i++)
if (triMeshes[i] != NULL)
delete triMeshes[i];
}
M3DTriangleMesh* M3DModel::getTriMesh(uint32 n)
{
if (n < triMeshes.size())
return triMeshes[n];
else
return NULL;
}
uint32 M3DModel::getTriMeshCount()
{
return triMeshes.size();
}
void M3DModel::addTriMesh(M3DTriangleMesh* triMesh)
{
triMeshes.insert(triMeshes.end(), triMesh);
}
void M3DModel::setName(const string _name)
{
name = _name;
}
const string M3DModel::getName() const
{
return name;
}
M3DScene::M3DScene()
{
}
M3DScene::~M3DScene()
{
int i;
for (i = 0; i < models.size(); i++)
if (models[i] != NULL)
delete models[i];
for (i = 0; i < materials.size(); i++)
if (materials[i] != NULL)
delete materials[i];
}
M3DModel* M3DScene::getModel(uint32 n) const
{
if (n < models.size())
return models[n];
else
return NULL;
}
uint32 M3DScene::getModelCount() const
{
return models.size();
}
void M3DScene::addModel(M3DModel* model)
{
models.insert(models.end(), model);
}
M3DMaterial* M3DScene::getMaterial(uint32 n) const
{
if (n < materials.size())
return materials[n];
else
return NULL;
}
uint32 M3DScene::getMaterialCount() const
{
return materials.size();
}
void M3DScene::addMaterial(M3DMaterial* material)
{
materials.insert(materials.end(), material);
}
M3DColor M3DScene::getBackgroundColor() const
{
return backgroundColor;
}
void M3DScene::setBackgroundColor(M3DColor color)
{
backgroundColor = color;
}

126
src/3dsmodel.h 100644
View File

@ -0,0 +1,126 @@
// 3dsmodel.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _3DSMODEL_H_
#define _3DSMODEL_H_
#include <vector>
#include <string>
#include "basictypes.h"
#include "vecmath.h"
class M3DColor
{
public:
M3DColor();
M3DColor(float, float, float);
public:
float red, green, blue;
};
class M3DMaterial
{
public:
M3DMaterial();
std::string getName() const;
void setName(std::string);
M3DColor getAmbientColor() const;
void setAmbientColor(M3DColor);
M3DColor getDiffuseColor() const;
void setDiffuseColor(M3DColor);
M3DColor getSpecularColor() const;
void setSpecularColor(M3DColor);
private:
std::string name;
M3DColor ambient;
M3DColor diffuse;
M3DColor specular;
};
class M3DTriangleMesh
{
public:
M3DTriangleMesh();
~M3DTriangleMesh();
Mat4f getMatrix() const;
void setMatrix(const Mat4f&);
Point3f getVertex(uint16) const;
uint16 getVertexCount() const;
void addVertex(Point3f);
void getFace(uint16, uint16&, uint16&, uint16&) const;
uint16 getFaceCount() const;
void addFace(uint16, uint16, uint16);
void addSmoothingGroups(uint32);
uint32 getSmoothingGroups(uint16) const;
uint16 getSmoothingGroupCount() const;
std::string getMaterialName() const;
void setMaterialName(std::string);
private:
std::vector<Point3f> points;
std::vector<uint16> faces;
std::vector<uint32> smoothingGroups;
Mat4f matrix;
std::string materialName;
};
class M3DModel
{
public:
M3DModel();
~M3DModel();
M3DTriangleMesh* getTriMesh(uint32);
uint32 getTriMeshCount();
void addTriMesh(M3DTriangleMesh*);
void setName(const std::string);
const std::string getName() const;
private:
std::string name;
std::vector<M3DTriangleMesh*> triMeshes;
};
class M3DScene
{
public:
M3DScene();
~M3DScene();
M3DModel* getModel(uint32) const;
uint32 getModelCount() const;
void addModel(M3DModel*);
M3DMaterial* getMaterial(uint32) const;
uint32 getMaterialCount() const;
void addMaterial(M3DMaterial*);
M3DColor getBackgroundColor() const;
void setBackgroundColor(M3DColor);
private:
std::vector<M3DModel*> models;
std::vector<M3DMaterial*> materials;
M3DColor backgroundColor;
};
#endif // _3DSMODEL_H_

645
src/3dsread.cpp 100644
View File

@ -0,0 +1,645 @@
// 3dsread.cpp
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iomanip>
#include "vecmath.h"
#include "3dschunk.h"
#include "3dsmodel.h"
#include "3dsread.h"
using namespace std;
typedef bool (*ProcessChunkFunc)(ifstream& in,
unsigned short chunkType,
int contentSize,
void*);
static int read3DSChunk(ifstream& in,
ProcessChunkFunc chunkFunc,
void* obj);
// For pretty printing debug info
static int logIndent = 0;
static int readInt(ifstream& in)
{
unsigned char b[4];
in.read(reinterpret_cast<char*>(b), 4);
return ((int) b[3] << 24) + ((int) b[2] << 16)
+ ((int) b[1] << 8) + (int) b[0];
}
static short readShort(ifstream& in)
{
unsigned char b[2];
in.read(reinterpret_cast<char*>(b), 2);
return ((short) b[1] << 8) + (short) b[0];
}
static unsigned short readUshort(ifstream& in)
{
unsigned char b[2];
in.read(reinterpret_cast<char*>(b), 2);
return ((unsigned short) b[1] << 8) + (unsigned short) b[0];
}
static char readChar(ifstream& in)
{
char c;
in.read(&c, 1);
return c;
}
static int readString(ifstream& in, char* s, int maxLength)
{
for (int count = 0; count < maxLength; count++)
{
in.read(s + count, 1);
if (s[count] == '\0')
break;
}
return count;
}
static string readString(ifstream& in)
{
char s[1024];
int maxLength = sizeof(s);
for (int count = 0; count < maxLength; count++)
{
in.read(s + count, 1);
if (s[count] == '\0')
break;
}
return string(s);
}
static float readFloat(ifstream& in)
{
int i = readInt(in);
return *((float*) &i);
}
static void skipBytes(ifstream& in, int count)
{
char c;
while (count-- > 0)
in.get(c);
}
void indent()
{
for (int i = 0; i < logIndent; i++)
cout << " ";
}
void logChunk(uint16 chunkType, int chunkSize)
{
char* name = NULL;
switch (chunkType)
{
case M3DCHUNK_NULL:
name = "M3DCHUNK_NULL"; break;
case M3DCHUNK_VERSION:
name = "M3DCHUNK_VERSION"; break;
case M3DCHUNK_COLOR_FLOAT:
name = "M3DCHUNK_COLOR_FLOAT"; break;
case M3DCHUNK_COLOR_24:
name = "M3DCHUNK_COLOR_24"; break;
case M3DCHUNK_LIN_COLOR_F:
name = "M3DCHUNK_LIN_COLOR_F"; break;
case M3DCHUNK_INT_PERCENTAGE:
name = "M3DCHUNK_INT_PERCENTAGE"; break;
case M3DCHUNK_FLOAT_PERCENTAGE:
name = "M3DCHUNK_FLOAT_PERCENTAGE"; break;
case M3DCHUNK_MASTER_SCALE:
name = "M3DCHUNK_MASTER_SCALE"; break;
case M3DCHUNK_BACKGROUND_COLOR:
name = "M3DCHUNK_BACKGROUND_COLOR"; break;
case M3DCHUNK_MESHDATA:
name = "M3DCHUNK_MESHDATA"; break;
case M3DCHUNK_MESH_VERSION:
name = "M3DCHUNK_MESHVERSION"; break;
case M3DCHUNK_NAMED_OBJECT:
name = "M3DCHUNK_NAMED_OBJECT"; break;
case M3DCHUNK_TRIANGLE_MESH:
name = "M3DCHUNK_TRIANGLE_MESH"; break;
case M3DCHUNK_POINT_ARRAY:
name = "M3DCHUNK_POINT_ARRAY"; break;
case M3DCHUNK_POINT_FLAG_ARRAY:
name = "M3DCHUNK_POINT_FLAG_ARRAY"; break;
case M3DCHUNK_FACE_ARRAY:
name = "M3DCHUNK_FACE_ARRAY"; break;
case M3DCHUNK_MESH_MATERIAL_GROUP:
name = "M3DCHUNK_MESH_MATERIAL_GROUP"; break;
case M3DCHUNK_MESH_TEXTURE_COORDS:
name = "M3DCHUNK_MESH_TEXTURE_COORDS"; break;
case M3DCHUNK_MESH_SMOOTH_GROUP:
name = "M3DCHUNK_MESH_SMOOTH_GROUP"; break;
case M3DCHUNK_MESH_MATRIX:
name = "M3DCHUNK_MESH_MATRIX"; break;
case M3DCHUNK_MAGIC:
name = "M3DCHUNK_MAGIC"; break;
case M3DCHUNK_MATERIAL_NAME:
name = "M3DCHUNK_MATERIAL_NAME"; break;
case M3DCHUNK_MATERIAL_AMBIENT:
name = "M3DCHUNK_MATERIAL_AMBIENT"; break;
case M3DCHUNK_MATERIAL_DIFFUSE:
name = "M3DCHUNK_MATERIAL_DIFFUSE"; break;
case M3DCHUNK_MATERIAL_SPECULAR:
name = "M3DCHUNK_MATERIAL_SPECULAR"; break;
case M3DCHUNK_MATERIAL_SHININESS:
name = "M3DCHUNK_MATERIAL_SHININESS"; break;
case M3DCHUNK_MATERIAL_SHIN2PCT:
name = "M3DCHUNK_MATERIAL_SHIN2PCT"; break;
case M3DCHUNK_MATERIAL_TRANSPARENCY:
name = "M3DCHUNK_MATERIAL_TRANSPARENCY"; break;
case M3DCHUNK_MATERIAL_XPFALL:
name = "M3DCHUNK_MATERIAL_XPFALL"; break;
case M3DCHUNK_MATERIAL_REFBLUR:
name = "M3DCHUNK_MATERIAL_REFBLUR"; break;
case M3DCHUNK_MATERIAL_ENTRY:
name = "M3DCHUNK_MATERIAL_ENTRY"; break;
case M3DCHUNK_KFDATA:
name = "M3DCHUNK_KFDATA";
default:
break;
}
indent();
if (name == NULL)
{
cout << "Chunk ID " << setw(4) << hex << setfill('0') << chunkType;
cout << setw(0) << dec << ", size = " << chunkSize << '\n';
}
else
{
cout << name << ", size = " << chunkSize << '\n';
}
cout.flush();
}
int read3DSChunk(ifstream& in,
ProcessChunkFunc chunkFunc,
void* obj)
{
unsigned short chunkType = readUshort(in);
int chunkSize = readInt(in);
int contentSize = chunkSize - 6;
logChunk(chunkType, chunkSize);
bool chunkWasRead = chunkFunc(in, chunkType, contentSize, obj);
if (!chunkWasRead)
{
skipBytes(in, contentSize);
}
return chunkSize;
}
int read3DSChunks(ifstream& in,
int nBytes,
ProcessChunkFunc chunkFunc,
void* obj)
{
int bytesRead = 0;
logIndent++;
while (bytesRead < nBytes)
bytesRead += read3DSChunk(in, chunkFunc, obj);
logIndent--;
if (bytesRead != nBytes)
cout << "Expected " << nBytes << " bytes but read " << bytesRead << '\n';
return bytesRead;
}
M3DColor readColor(ifstream& in, int nBytes)
{
unsigned char r = (unsigned char) readChar(in);
unsigned char g = (unsigned char) readChar(in);
unsigned char b = (unsigned char) readChar(in);
return M3DColor((float) r / 255.0f,
(float) g / 255.0f,
(float) b / 255.0f);
}
M3DColor readFloatColor(ifstream& in, int nBytes)
{
float r = readFloat(in);
float g = readFloat(in);
float b = readFloat(in);
return M3DColor((float) r / 255.0f,
(float) g / 255.0f,
(float) b / 255.0f);
}
Mat4f readMeshMatrix(ifstream& in, int nBytes)
{
float m00 = readFloat(in);
float m01 = readFloat(in);
float m02 = readFloat(in);
float m10 = readFloat(in);
float m11 = readFloat(in);
float m12 = readFloat(in);
float m20 = readFloat(in);
float m21 = readFloat(in);
float m22 = readFloat(in);
float m30 = readFloat(in);
float m31 = readFloat(in);
float m32 = readFloat(in);
cout << m00 << " " << m01 << " " << m02 << '\n';
cout << m10 << " " << m11 << " " << m12 << '\n';
cout << m20 << " " << m21 << " " << m22 << '\n';
cout << m30 << " " << m31 << " " << m32 << '\n';
return Mat4f(Vec4f(m00, m01, m02, 0),
Vec4f(m10, m11, m12, 0),
Vec4f(m20, m21, m22, 0),
Vec4f(m30, m31, m32, 1));
}
bool stubProcessChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
return false;
}
void readPointArray(ifstream& in, M3DTriangleMesh* triMesh)
{
uint16 nPoints = readUshort(in);
for (int i = 0; i < (int) nPoints; i++)
{
float x = readFloat(in);
float y = readFloat(in);
float z = readFloat(in);
triMesh->addVertex(Point3f(x, y, z));
}
}
bool processFaceArrayChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DTriangleMesh* triMesh = (M3DTriangleMesh*) obj;
if (chunkType == M3DCHUNK_MESH_MATERIAL_GROUP)
{
// For now, we just assume that there is only one material group
// per triangle mesh, and that the material applies to all faces in
// the mesh.
string materialName = readString(in);
uint16 nFaces = readUshort(in);
for (uint16 i = 0; i < nFaces; i++)
{
readUshort(in);
}
triMesh->setMaterialName(materialName);
return true;
}
else if (chunkType == M3DCHUNK_MESH_SMOOTH_GROUP)
{
uint16 nFaces = triMesh->getFaceCount();
for (uint16 i = 0; i < nFaces; i++)
{
uint32 groups = (uint32) readInt(in);
// cout << setw(8) << hex << setfill('0') << groups << dec << setw(0) << '\n';
triMesh->addSmoothingGroups(groups);
}
return true;
}
else
{
return false;
}
}
void readFaceArray(ifstream& in, M3DTriangleMesh* triMesh, int contentSize)
{
uint16 nFaces = readUshort(in);
for (int i = 0; i < (int) nFaces; i++)
{
uint16 v0 = readUshort(in);
uint16 v1 = readUshort(in);
uint16 v2 = readUshort(in);
uint16 flags = readUshort(in);
triMesh->addFace(v0, v1, v2);
}
int bytesLeft = contentSize - (8 * nFaces + 2);
if (bytesLeft > 0)
{
read3DSChunks(in,
bytesLeft,
processFaceArrayChunk,
(void*) triMesh);
}
}
bool processTriMeshChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DTriangleMesh* triMesh = (M3DTriangleMesh*) obj;
if (chunkType == M3DCHUNK_POINT_ARRAY)
{
readPointArray(in, triMesh);
return true;
}
else if (chunkType == M3DCHUNK_FACE_ARRAY)
{
readFaceArray(in, triMesh, contentSize);
return true;
}
else if (chunkType == M3DCHUNK_MESH_MATRIX)
{
triMesh->setMatrix(readMeshMatrix(in, contentSize));
return true;
}
else
{
return false;
}
}
bool processModelChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DModel* model = (M3DModel*) obj;
if (chunkType == M3DCHUNK_TRIANGLE_MESH)
{
M3DTriangleMesh* triMesh = new M3DTriangleMesh();
read3DSChunks(in, contentSize, processTriMeshChunk, (void*) triMesh);
model->addTriMesh(triMesh);
return true;
}
else
{
return false;
}
}
bool processColorChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DColor* color = (M3DColor*) obj;
if (chunkType == M3DCHUNK_COLOR_24)
{
*color = readColor(in, contentSize);
return true;
}
else if (chunkType == (M3DCHUNK_COLOR_FLOAT))
{
*color = readFloatColor(in, contentSize);
return true;
}
else
{
return false;
}
}
bool processMaterialChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DMaterial* material = (M3DMaterial*) obj;
if (chunkType == M3DCHUNK_MATERIAL_NAME)
{
string name = readString(in);
material->setName(name);
return true;
}
else if (chunkType == M3DCHUNK_MATERIAL_AMBIENT)
{
M3DColor ambient;
read3DSChunks(in, contentSize, processColorChunk, (void*) &ambient);
material->setAmbientColor(ambient);
return true;
}
else if (chunkType == M3DCHUNK_MATERIAL_DIFFUSE)
{
M3DColor diffuse;
read3DSChunks(in, contentSize, processColorChunk, (void*) &diffuse);
material->setDiffuseColor(diffuse);
return true;
}
else if (chunkType == M3DCHUNK_MATERIAL_SPECULAR)
{
M3DColor specular;
read3DSChunks(in, contentSize, processColorChunk, (void*) &specular);
material->setSpecularColor(specular);
return true;
}
else
{
return false;
}
}
bool processSceneChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DScene* scene = (M3DScene*) obj;
if (chunkType == M3DCHUNK_NAMED_OBJECT)
{
string name = readString(in);
M3DModel* model = new M3DModel();
model->setName(name);
indent(); cout << " [" << name << "]\n";
read3DSChunks(in,
contentSize - (name.length() + 1),
processModelChunk,
(void*) model);
scene->addModel(model);
return true;
}
else if (chunkType == M3DCHUNK_MATERIAL_ENTRY)
{
M3DMaterial* material = new M3DMaterial();
read3DSChunks(in,
contentSize,
processMaterialChunk,
(void*) material);
scene->addMaterial(material);
return true;
}
else if (chunkType == M3DCHUNK_BACKGROUND_COLOR)
{
M3DColor color;
read3DSChunks(in, contentSize, processColorChunk, (void*) &color);
scene->setBackgroundColor(color);
return true;
}
else
{
return false;
}
}
bool processTopLevelChunk(ifstream& in,
unsigned short chunkType,
int contentSize,
void* obj)
{
M3DScene* scene = (M3DScene*) obj;
if (chunkType == M3DCHUNK_MESHDATA)
{
read3DSChunks(in, contentSize, processSceneChunk, (void*) scene);
return true;
}
else
{
return false;
}
}
M3DScene* Read3DSFile(ifstream& in)
{
unsigned short chunkType = readUshort(in);
if (chunkType != M3DCHUNK_MAGIC)
{
cerr << "Wrong magic number in header\n";
return NULL;
}
int chunkSize = readInt(in);
if (in.bad())
{
cerr << "Error reading 3DS file.\n";
return NULL;
}
cout << "3DS file, " << chunkSize << " bytes\n";
M3DScene* scene = new M3DScene();
int contentSize = chunkSize - 6;
read3DSChunks(in, contentSize, processTopLevelChunk, (void*) scene);
return scene;
}
M3DScene* Read3DSFile(string filename)
{
ifstream in(filename.c_str(), ios::in | ios::binary);
if (!in.good())
{
cerr << "Error opening " << filename << '\n';
return NULL;
}
else
{
M3DScene* scene = Read3DSFile(in);
in.close();
return scene;
}
}
M3DScene* Read3DSFile(char* filename)
{
ifstream in(filename, ios::in | ios::binary);
if (!in.good())
{
cerr << "Error opening " << filename << '\n';
return NULL;
}
else
{
M3DScene* scene = Read3DSFile(in);
in.close();
return scene;
}
}
#if 0
int main(int argc, char* argv[])
{
if (argc != 2)
{
cerr << "Usage: 3dsread <filename>\n";
exit(1);
}
ifstream in(argv[1], ios::in | ios::binary);
if (!in.good())
{
cerr << "Error opening " << argv[1] << '\n';
exit(1);
}
else
{
read3DSFile(in);
in.close();
}
return 0;
}
#endif

22
src/3dsread.h 100644
View File

@ -0,0 +1,22 @@
// 3dsread.h
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _3DSREAD_H_
#define _3DSREAD_H_
#include <iostream>
#include <fstream>
#include <string>
#include "3dsmodel.h"
M3DScene* Read3DSFile(std::ifstream& in);
M3DScene* Read3DSFile(std::string filename);
M3DScene* Read3DSFile(char* filename);
#endif // _3DSREAD_H_

1341
src/Ijl.h 100644

File diff suppressed because it is too large Load Diff

113
src/aabox.h 100644
View File

@ -0,0 +1,113 @@
// aabox.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Axis-aligned bounding box class
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _AABOX_H_
#define _AABOX_H_
#include "vecmath.h"
class AxisAlignedBox
{
public:
inline AxisAlignedBox();
AxisAlignedBox(Point3f _min, Point3f _max) :
minimum(_min), maximum(_max) {};
AxisAlignedBox(Point3f center) :
minimum(center), maximum(center) {};
inline Point3f getMinimum() const;
inline Point3f getMaximum() const;
inline Point3f getCenter() const;
inline Vec3f getExtents() const;
inline bool empty() const;
inline bool contains(const Point3f&) const;
inline void include(const Point3f&);
inline void include(const AxisAlignedBox&);
private:
Point3f minimum;
Point3f maximum;
};
AxisAlignedBox::AxisAlignedBox() :
minimum(1.0e20f, 1.0e20f, 1.0e20f),
maximum(-1.0e20f, -1.0e20f, -1.0e20f)
{
}
Point3f AxisAlignedBox::getMinimum() const
{
return minimum;
}
Point3f AxisAlignedBox::getMaximum() const
{
return maximum;
}
Point3f AxisAlignedBox::getCenter() const
{
return Point3f((minimum.x + maximum.x) * 0.5f,
(minimum.y + maximum.y) * 0.5f,
(minimum.z + maximum.z) * 0.5f);
}
Vec3f AxisAlignedBox::getExtents() const
{
return maximum - minimum;
}
bool AxisAlignedBox::empty() const
{
return maximum.x < minimum.x || maximum.y < minimum.y || maximum.z < minimum.z;
}
bool AxisAlignedBox::contains(const Point3f& p) const
{
return (p.x >= minimum.x && p.x <= maximum.x &&
p.y >= minimum.y && p.y <= maximum.y &&
p.z >= minimum.z && p.z <= maximum.z);
}
void AxisAlignedBox::include(const Point3f& p)
{
if (p.x < minimum.x) minimum.x = p.x;
if (p.x > maximum.x) maximum.x = p.x;
if (p.y < minimum.y) minimum.y = p.y;
if (p.y > maximum.y) maximum.y = p.y;
if (p.z < minimum.z) minimum.z = p.z;
if (p.z > maximum.z) maximum.z = p.z;
}
void AxisAlignedBox::include(const AxisAlignedBox& b)
{
if (b.minimum.x < minimum.x) minimum.x = b.minimum.x;
if (b.maximum.x > maximum.x) maximum.x = b.maximum.x;
if (b.minimum.y < minimum.y) minimum.y = b.minimum.y;
if (b.maximum.y > maximum.y) maximum.y = b.maximum.y;
if (b.minimum.z < minimum.z) minimum.z = b.minimum.z;
if (b.maximum.z > maximum.z) maximum.z = b.maximum.z;
}
#if 0
AxisAlignedBox union(const AxisAlignedBox& a, const AxisAlignedBox& b)
{
AxisAlignedBox box(a);
box.union(b);
return box;
}
#endif
#endif // _AABOX_H_

242
src/astro.cpp 100644
View File

@ -0,0 +1,242 @@
// astro.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include <iomanip>
#include "celestia.h"
#include "astro.h"
using namespace std;
#define SOLAR_ABSMAG 4.83f
#define LN_MAG 1.085736
#define LY_PER_PARSEC 3.26
#define KM_PER_LY 9466411842000.000
#define KM_PER_AU 149597870.7
#define AU_PER_LY (KM_PER_LY / KM_PER_AU)
// epoch J2000: 12 UT on 1 Jan 2000
#define J2000 2451545.0
// epoch B1950: 22:09 UT on 21 Dec 1949
#define B1950 2433282.423
float astro::lumToAbsMag(float lum)
{
return (float) (SOLAR_ABSMAG - log(lum) * LN_MAG);
}
// Return the apparent magnitude of a star with lum times solar
// luminosity viewed at lyrs light years
float astro::lumToAppMag(float lum, float lyrs)
{
return absToAppMag(lumToAbsMag(lum), lyrs);
}
float astro::absMagToLum(float mag)
{
return (float) exp((SOLAR_ABSMAG - mag) / LN_MAG);
}
float astro::appMagToLum(float mag, float lyrs)
{
return absMagToLum(appToAbsMag(mag, lyrs));
}
float astro::absToAppMag(float absMag, float lyrs)
{
return (float) (absMag - 5 + 5 * log10(lyrs / LY_PER_PARSEC));
}
float astro::appToAbsMag(float appMag, float lyrs)
{
return (float) (appMag + 5 - 5 * log10(lyrs / LY_PER_PARSEC));
}
float astro::lightYearsToParsecs(float ly)
{
return ly / (float) LY_PER_PARSEC;
}
float astro::parsecsToLightYears(float pc)
{
return pc * (float) LY_PER_PARSEC;
}
float astro::lightYearsToKilometers(float ly)
{
return ly * (float) KM_PER_LY;
}
double astro::lightYearsToKilometers(double ly)
{
return ly * KM_PER_LY;
}
float astro::kilometersToLightYears(float km)
{
return km / (float) KM_PER_LY;
}
double astro::kilometersToLightYears(double km)
{
return km / KM_PER_LY;
}
float astro::lightYearsToAU(float ly)
{
return ly * (float) AU_PER_LY;
}
double astro::lightYearsToAU(double ly)
{
return ly * AU_PER_LY;
}
float astro::AUtoLightYears(float au)
{
return au / (float) AU_PER_LY;
}
float astro::AUtoKilometers(float au)
{
return au * (float) KM_PER_AU;
}
float astro::kilometersToAU(float km)
{
return km / (float) KM_PER_AU;
}
double astro::secondsToJulianDate(double sec)
{
return sec / 86400.0;
}
double astro::julianDateToSeconds(double jd)
{
return jd * 86400.0;
}
// Compute the fraction of a sphere which is illuminated and visible
// to a viewer. The source of illumination is assumed to be at (0, 0, 0)
float astro::sphereIlluminationFraction(Point3d spherePos,
Point3d viewerPos)
{
return 1.0f;
}
// Convert the position in univeral coordinates to a star-centric
// coordinates in units of kilometers. Note that there are three different
// precisions used here: star coordinates are stored as floats in units of
// light years, position within a solar system are doubles in units of
// kilometers, and p is highest-precision in units of light years.
Point3d astro::heliocentricPosition(UniversalCoord universal,
Point3f starPosition)
{
// Get the offset vector
Vec3d v = universal - Point3d(starPosition.x, starPosition.y, starPosition.z);
// . . . and convert it to kilometers
return Point3d(lightYearsToKilometers(v.x),
lightYearsToKilometers(v.y),
lightYearsToKilometers(v.z));
}
// universalPosition is the inverse operation of heliocentricPosition
UniversalCoord astro::universalPosition(Point3d heliocentric,
Point3f starPosition)
{
return UniversalCoord(starPosition) +
Vec3d(kilometersToLightYears(heliocentric.x),
kilometersToLightYears(heliocentric.y),
kilometersToLightYears(heliocentric.z));
}
astro::Date::Date(int Y, int M, int D)
{
year = Y;
month = M;
day = D;
hour = 0;
minute = 0;
seconds = 0.0;
}
astro::Date::Date(double jd)
{
int a = (int) (jd + 0.5);
double c;
if (a < 2299161)
{
c = a + 1524;
}
else
{
double b = (int) ((a - 1867216.25) / 36524.25);
c = a + b - (int) (b / 4) + 1525;
}
int d = (int) ((c - 122.1) / 365.25);
int e = (int) (365.25 * d);
int f = (int) ((c - e) / 30.6001);
double dday = c - e - (int) (30.6001 * f) + ((jd + 0.5) - (int) (jd + 0.5));
month = f - 1 - 12 * (int) (f / 14.0);
year = d - 4715 - (int) ((7.0 + month) / 10.0);
day = (int) dday;
double dhour = (dday - day) * 24;
hour = (int) dhour;
double dminute = (dhour - hour) * 60;
minute = (int) dminute;
seconds = (dminute - minute) * 60;
}
// Convert a calendar date to a Julian date
astro::Date::operator double() const
{
int y = year, m = month;
if (month <= 2)
{
y = year - 1;
m = month + 12;
}
// Correct for the lost days in Oct 1582 when the Gregorian calendar
// replaced the Julian calendar.
int B = -2;
if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15))))
{
B = y / 400 - y / 100;
}
return (floor(365.25 * y) +
floor(30.6001 * (m + 1)) + B + 1720996.5 +
day + hour / 24.0 + minute / 1440.0 + seconds / 86400.0);
}
ostream& operator<<(ostream& s, const astro::Date d)
{
s << d.year << ' ' << setw(2) << setfill('0') << d.month << ' ';
s << setw(2) << setfill('0') << d.day << ' ';
s << setw(2) << setfill('0') << d.hour << ':';
s << setw(2) << setfill('0') << d.minute << ':';
s << setw(2) << setfill('0') << (int) d.seconds;
return s;
}

72
src/astro.h 100644
View File

@ -0,0 +1,72 @@
// astro.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _ASTRO_H_
#define _ASTRO_H_
#include <iostream>
#include "vecmath.h"
#include "univcoord.h"
namespace astro
{
class Date
{
public:
Date(int Y, int M, int D);
Date(double);
operator double() const;
public:
int year;
int month;
int day;
int hour;
int minute;
double seconds;
};
float lumToAbsMag(float lum);
float lumToAppMag(float lum, float lyrs);
float absMagToLum(float mag);
float appMagToLum(float mag, float lyrs);
float absToAppMag(float absMag, float lyrs);
float appToAbsMag(float appMag, float lyrs);
float lightYearsToParsecs(float);
float parsecsToLightYears(float);
float lightYearsToKilometers(float);
double lightYearsToKilometers(double);
float kilometersToLightYears(float);
double kilometersToLightYears(double);
float lightYearsToAU(float);
double lightYearsToAU(double);
float AUtoLightYears(float);
float AUtoKilometers(float);
float kilometersToAU(float);
double secondsToJulianDate(double);
double julianDateToSeconds(double);
float sphereIlluminationFraction(Point3d spherePos,
Point3d viewerPos);
Point3d heliocentricPosition(UniversalCoord universal,
Point3f starPosition);
UniversalCoord universalPosition(Point3d heliocentric,
Point3f starPosition);
};
// Convert a date structure to a Julian date
std::ostream& operator<<(std::ostream& s, const astro::Date);
#endif // _ASTRO_H_

24
src/basictypes.h 100644
View File

@ -0,0 +1,24 @@
// basictypes.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _BASICTYPES_H_
#define _BASICTYPES_H_
typedef unsigned int uint;
// Fixed size types
typedef int int32;
typedef unsigned int uint32;
typedef short int16;
typedef unsigned short uint16;
typedef char int8;
typedef unsigned char uint8;
#endif // _BASICTYPES_H_

187
src/bigfix.cpp 100644
View File

@ -0,0 +1,187 @@
// bigfix.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <math.h>
#include <stdio.h>
#include "bigfix.h"
/*** Constructors ***/
// Create a BigFix initialized to zero
BigFix::BigFix()
{
for (int i = 0; i < N_WORDS; i++)
n[i] = 0;
}
BigFix::BigFix(int i)
{
n[N_WORDS / 2] = (unsigned short) (i & 0xffff);
n[N_WORDS / 2 + 1] = (unsigned short) ((i >> 16) & 0xffff);
// Sign extend if negative
if (i < 0)
{
for (int j = N_WORDS / 2 + 2; j < N_WORDS; j++)
n[j] = 0xffff;
}
}
BigFix::BigFix(double d)
{
int sign = 1;
if (d < 0)
{
sign = -1;
d = -d;
}
double e = floor(d / (65536.0 * 65536.0 * 65536.0));
// Check for overflow
if (e < 32767)
{
n[7] = (unsigned short) e;
d -= n[7] * 65536 * 65536 * 65536;
n[6] = (unsigned short) (d / (65536.0 * 65536.0));
d -= n[6] * 65536 * 65536;
n[5] = (unsigned short) (d / 65536);
d -= n[5] * 65536;
n[4] = (unsigned short) d;
d -= n[4];
n[3] = (unsigned short) (d * 65536);
d -= n[3] / 65536;
n[2] = (unsigned short) (d * 65536 * 65536);
d -= n[2] / 65536;
n[1] = (unsigned short) (d * 65536 * 65536 * 65536);
d -= n[1] / 65536;
n[0] = (unsigned short) (d * 65536 * 65536 * 65536 * 65536);
}
if (sign < 0)
*this = -*this;
}
BigFix::operator double() const
{
double d = 0;
double e = 1.0 / (65536.0 * 65536.0 * 65536.0 * 65536.0);
BigFix f;
if ((n[N_WORDS - 1] & 0x8000) == 0)
f = *this;
else
f = -*this;
for (int i = 0; i < N_WORDS; i++)
{
d += e * f.n[i];
e *= 65536;
}
return ((n[N_WORDS - 1] & 0x8000) == 0) ? d : -d;
}
BigFix::operator float() const
{
return (float) (double) *this;
}
BigFix BigFix::operator-() const
{
int i;
BigFix f;
for (i = 0; i < N_WORDS; i++)
f.n[i] = ~n[i];
unsigned int carry = 1;
i = 0;
while (carry != 0 && i < N_WORDS)
{
unsigned int m = f.n[i] + carry;
f.n[i] = (unsigned short) (m & 0xffff);
carry = m >> 16;
i++;
}
return f;
}
BigFix operator+(BigFix a, BigFix b)
{
unsigned int carry = 0;
BigFix c;
for (int i = 0; i < N_WORDS; i++)
{
unsigned int m = a.n[i] + b.n[i] + carry;
c.n[i] = (unsigned short) (m & 0xffff);
carry = m >> 16;
}
return c;
}
BigFix operator-(BigFix a, BigFix b)
{
return a + -b;
}
BigFix operator*(BigFix a, BigFix b)
{
return BigFix();
}
bool operator==(BigFix a, BigFix b)
{
for (int i = 0; i < N_WORDS; i++)
if (a.n[i] != b.n[i])
return false;
return true;
}
bool operator!=(BigFix a, BigFix b)
{
return !(a == b);
}
int BigFix::sign()
{
if ((n[N_WORDS - 1] & 0x8000) != 0)
return -1;
for (int i = 0; i < N_WORDS - 1; i++)
if (n[N_WORDS] != 0)
return 1;
return 0;
}
// For debugging
void BigFix::dump()
{
for (int i = 7; i >= 0; i--)
printf("%04x ", n[i]);
printf("\n");
}

47
src/bigfix.h 100644
View File

@ -0,0 +1,47 @@
// bigfix.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// 128-bit fixed point (64.64) numbers for high-precision celestial
// coordinates. When you need millimeter accurate navigation across a scale
// of thousands of light years, doubles just don't do it.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _BIGFIX_H_
#define _BIGFIX_H_
#define N_WORDS 8
class BigFix
{
public:
BigFix();
BigFix(int);
BigFix(double);
operator double() const;
operator float() const;
BigFix operator-() const;
friend BigFix operator+(BigFix, BigFix);
friend BigFix operator-(BigFix, BigFix);
friend BigFix operator*(BigFix, BigFix);
friend bool operator==(BigFix, BigFix);
friend bool operator!=(BigFix, BigFix);
int sign();
// for debugging
void dump();
private:
unsigned short n[N_WORDS]; // high 16-bits is n[N_WORDS - 1]
};
#endif // _BIGFIX_H_

341
src/body.cpp 100644
View File

@ -0,0 +1,341 @@
// body.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
#include <stdlib.h>
#include "mathlib.h"
#include "astro.h"
#include "body.h"
using namespace std;
Body::Body(PlanetarySystem* _system) :
orbit(NULL),
satellites(NULL),
rings(NULL),
rotationPeriod(1),
color(1.0f, 1.0f, 1.0f),
oblateness(0),
appearanceFlags(0)
{
system = _system;
}
PlanetarySystem* Body::getSystem() const
{
return system;
}
string Body::getName() const
{
return name;
}
void Body::setName(const string _name)
{
name = _name;
}
Orbit* Body::getOrbit() const
{
return orbit;
}
void Body::setOrbit(Orbit* _orbit)
{
if (orbit == NULL)
delete orbit;
orbit = _orbit;
}
float Body::getRadius() const
{
return radius;
}
void Body::setRadius(float _radius)
{
radius = _radius;
}
float Body::getMass() const
{
return mass;
}
void Body::setMass(float _mass)
{
mass = _mass;
}
float Body::getOblateness() const
{
return oblateness;
}
void Body::setOblateness(float _oblateness)
{
oblateness = _oblateness;
}
float Body::getObliquity() const
{
return obliquity;
}
void Body::setObliquity(float _obliquity)
{
obliquity = _obliquity;
}
float Body::getAlbedo() const
{
return albedo;
}
void Body::setAlbedo(float _albedo)
{
albedo = _albedo;
}
float Body::getRotationPeriod() const
{
return rotationPeriod;
}
void Body::setRotationPeriod(float _rotationPeriod)
{
rotationPeriod = _rotationPeriod;
}
Color Body::getColor() const
{
return color;
}
void Body::setColor(Color _color)
{
color = _color;
}
string Body::getTexture() const
{
return texture;
}
void Body::setTexture(const string _texture)
{
texture = _texture;
}
string Body::getMesh() const
{
return mesh;
}
void Body::setMesh(const string _mesh)
{
mesh = _mesh;
}
uint32 Body::getAppearanceFlags() const
{
return appearanceFlags;
}
void Body::setAppearanceFlags(uint32 flags)
{
appearanceFlags = flags;
}
bool Body::getAppearanceFlag(uint32 flag) const
{
return (appearanceFlags & flag) != 0;
}
void Body::setAppearanceFlag(uint32 flag, bool on)
{
appearanceFlags &= ~flag;
appearanceFlags |= on ? flag : 0;
}
const PlanetarySystem* Body::getSatellites() const
{
return satellites;
}
void Body::setSatellites(PlanetarySystem* ssys)
{
satellites = ssys;
}
RingSystem* Body::getRings() const
{
return rings;
}
void Body::setRings(RingSystem& _rings)
{
if (rings == NULL)
rings = new RingSystem(_rings);
else
*rings = _rings;
}
// Get a matrix which converts from local to heliocentric coordinates
Mat4d Body::getLocalToHeliocentric(double when)
{
Point3d pos = orbit->positionAtTime(when);
Mat4d frame = Mat4d::xrotation(-obliquity) * Mat4d::translation(pos);
// Recurse up the hierarchy . . .
if (system != NULL && system->getPrimaryBody() != NULL)
frame = frame * system->getPrimaryBody()->getLocalToHeliocentric(when);
return frame;
}
// Return the position of the center of the body in heliocentric coordinates
Point3d Body::getHeliocentricPosition(double when)
{
return Point3d(0.0, 0.0, 0.0) * getLocalToHeliocentric(when);
}
#define SOLAR_IRRADIANCE 1367.6
#define SOLAR_POWER 3.8462e26
float Body::getLuminosity(const Star& sun,
float distanceFromSun) const
{
// Compute the total power of the star in Watts
double power = SOLAR_POWER * sun.getLuminosity();
// Compute the irradiance at a distance of 1au from the star in W/m^2
double irradiance = power / sphereArea(astro::AUtoKilometers(1.0) * 1000);
// Compute the irradiance at the body's distance from the star
double satIrradiance = power / sphereArea(distanceFromSun * 1000);
// Compute the total energy hitting the planet
double incidentEnergy = satIrradiance * circleArea(radius * 1000);
double reflectedEnergy = incidentEnergy * albedo;
// Compute the luminosity (i.e. power relative to solar power)
return (float) (reflectedEnergy / SOLAR_POWER);
}
float Body::getApparentMagnitude(const Star& sun,
float distanceFromSun,
float distanceFromViewer) const
{
return astro::lumToAppMag(getLuminosity(sun, distanceFromSun),
astro::kilometersToLightYears(distanceFromViewer));
}
// Return the apparent magnitude of the body, corrected for the phase.
float Body::getApparentMagnitude(const Star& sun,
const Vec3d& sunPosition,
const Vec3d& viewerPosition) const
{
double distanceToViewer = viewerPosition.length();
double distanceToSun = sunPosition.length();
float illuminatedFraction = (float) (1.0 + (viewerPosition / distanceToViewer) *
(sunPosition / distanceToSun)) / 2.0;
return astro::lumToAppMag(getLuminosity(sun, distanceToSun) * illuminatedFraction,
astro::kilometersToLightYears(distanceToViewer));
}
/**** Implementation of PlanetarySystem ****/
PlanetarySystem::PlanetarySystem(Body* _primary) : primary(_primary)
{
if (primary != NULL && primary->getSystem() != NULL)
starNumber = primary->getSystem()->getStarNumber();
else
starNumber = Star::InvalidStar;
}
PlanetarySystem::PlanetarySystem(uint32 _starNumber) :
primary(NULL), starNumber(_starNumber)
{
}
Body* PlanetarySystem::find(string _name, bool deepSearch) const
{
for (int i = 0; i < satellites.size(); i++)
{
if (satellites[i]->getName() == _name)
{
return satellites[i];
}
else if (deepSearch && satellites[i]->getSatellites() != NULL)
{
Body* body = satellites[i]->getSatellites()->find(_name, deepSearch);
if (body != NULL)
return body;
}
}
return NULL;
}
bool PlanetarySystem::traverse(TraversalFunc func, void* info) const
{
for (int i = 0; i < getSystemSize(); i++)
{
Body* body = getBody(i);
// assert(body != NULL);
if (!func(body, info))
return false;
if (body->getSatellites() != NULL)
{
if (!body->getSatellites()->traverse(func, info))
return false;
}
}
return true;
}

144
src/body.h 100644
View File

@ -0,0 +1,144 @@
// body.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
#ifndef _BODY_H_
#define _BODY_H_
#include <string>
#include <vector>
#include "color.h"
#include "orbit.h"
#include "star.h"
class Body;
class PlanetarySystem
{
public:
PlanetarySystem(Body* _primary);
PlanetarySystem(uint32 _starNumber);
uint32 getStarNumber() const { return starNumber; };
Body* getPrimaryBody() const { return primary; };
int getSystemSize() const { return satellites.size(); };
Body* getBody(int i) const { return satellites[i]; };
void addBody(Body* body) { satellites.insert(satellites.end(), body); };
enum TraversalResult
{
ContinueTraversal = 0,
StopTraversal = 1
};
typedef bool (*TraversalFunc)(Body*, void*);
bool traverse(TraversalFunc, void*) const;
Body* find(std::string, bool deepSearch = false) const;
private:
uint32 starNumber;
Body* primary;
std::vector<Body*> satellites;
};
class RingSystem
{
public:
float innerRadius;
float outerRadius;
Color color;
RingSystem(float inner, float outer) :
innerRadius(inner), outerRadius(outer), color(1.0f, 1.0f, 1.0f)
{ }
RingSystem(float inner, float outer, Color _color) :
innerRadius(inner), outerRadius(outer), color(_color)
{ }
};
class Body
{
public:
Body(PlanetarySystem*);
PlanetarySystem* getSystem() const;
std::string getName() const;
void setName(const std::string);
Orbit* getOrbit() const;
void setOrbit(Orbit*);
float getRadius() const;
void setRadius(float);
float getMass() const;
void setMass(float);
float getOblateness() const;
void setOblateness(float);
float getObliquity() const;
void setObliquity(float);
float getAlbedo() const;
void setAlbedo(float);
float getRotationPeriod() const;
void setRotationPeriod(float);
const PlanetarySystem* getSatellites() const;
void setSatellites(PlanetarySystem*);
RingSystem* getRings() const;
void setRings(RingSystem&);
void setColor(Color);
Color getColor() const;
void setTexture(std::string);
std::string getTexture() const;
void setMesh(std::string);
std::string getMesh() const;
void setAppearanceFlags(uint32);
uint32 getAppearanceFlags() const;
void setAppearanceFlag(uint32, bool);
bool getAppearanceFlag(uint32) const;
float getLuminosity(const Star& sun,
float distanceFromSun) const;
float getApparentMagnitude(const Star& sun,
float distanceFromSun,
float distanceFromViewer) const;
float getApparentMagnitude(const Star& sun,
const Vec3d& sunPosition,
const Vec3d& viewerPosition) const;
Mat4d getLocalToHeliocentric(double when);
Point3d getHeliocentricPosition(double when);
// Appearance flags
enum {
BlendTexture = 1,
};
private:
std::string name;
PlanetarySystem* system;
Orbit* orbit;
float radius;
float mass;
float oblateness;
float obliquity; // aka 'axial tilt'
float albedo;
float rotationPeriod;
Color color;
std::string texture;
std::string mesh;
uint32 appearanceFlags;
RingSystem* rings;
PlanetarySystem* satellites;
};
#endif // _BODY_H_

28
src/celestia.h 100644
View File

@ -0,0 +1,28 @@
// celestia.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _CELESTIA_H_
#define _CELESTIA_H_
#if _MSC_VER >= 1000
// Make VC shut up about long variable names from templates
#pragma warning(disable : 4786)
#endif // _MSC_VER
#ifndef DEBUG
#define DPRINTF //
#else
#define DPRINTF DebugPrint
extern void DebugPrint(char *format, ...);
#endif
extern void Log(char *format, ...);
#endif // _CELESTIA_H_

53
src/color.cpp 100644
View File

@ -0,0 +1,53 @@
// color.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "mathlib.h"
#include "color.h"
Color::Color()
{
c[Red] = c[Green] = c[Blue] = 0;
c[Alpha] = 0xff;
}
Color::Color(float r, float g, float b)
{
c[Red] = (unsigned char) (clamp(r) * 255.99f);
c[Green] = (unsigned char) (clamp(g) * 255.99f);
c[Blue] = (unsigned char) (clamp(b) * 255.99f);
c[Alpha] = 0xff;
}
Color::Color(float r, float g, float b, float a)
{
c[Red] = (unsigned char) (clamp(r) * 255.99f);
c[Green] = (unsigned char) (clamp(g) * 255.99f);
c[Blue] = (unsigned char) (clamp(b) * 255.99f);
c[Alpha] = (unsigned char) (clamp(a) * 255.99f);
}
Color::Color(unsigned char r, unsigned char g, unsigned char b)
{
c[Red] = r;
c[Green] = g;
c[Blue] = b;
c[Alpha] = 0xff;
}
Color::Color(Color& color, float alpha)
{
*this = color;
c[Alpha] = (unsigned char) (clamp(alpha) * 255.99f);
}

60
src/color.h 100644
View File

@ -0,0 +1,60 @@
// color.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _COLOR_H_
#define _COLOR_H_
class Color
{
public:
Color();
Color(float, float, float);
Color(float, float, float, float);
Color(unsigned char, unsigned char, unsigned char);
Color(Color&, float);
enum {
Red = 0,
Green = 1,
Blue = 2,
Alpha = 3
};
inline float red() const;
inline float green() const;
inline float blue() const;
inline float alpha() const;
private:
unsigned char c[4];
};
float Color::red() const
{
return c[Red] * (1.0f / 255.0f);
}
float Color::green() const
{
return c[Green] * (1.0f / 255.0f);
}
float Color::blue() const
{
return c[Blue] * (1.0f / 255.0f);
}
float Color::alpha() const
{
return c[Alpha] * (1.0f / 255.0f);
}
#endif // _COLOR_H_

121
src/config.cpp 100644
View File

@ -0,0 +1,121 @@
// config.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iostream>
#include <fstream>
#include "celestia.h"
#include "parser.h"
#include "config.h"
using namespace std;
CelestiaConfig* ReadCelestiaConfig(string filename)
{
ifstream configFile(filename.c_str());
if (!configFile.good())
{
DPRINTF("Error opening config file.");
return NULL;
}
Tokenizer tokenizer(&configFile);
Parser parser(&tokenizer);
if (tokenizer.nextToken() != Tokenizer::TokenName)
{
DPRINTF("%s:%d 'Configuration' expected.\n", filename.c_str(),
tokenizer.getLineNumber());
return NULL;
}
if (tokenizer.getStringValue() != "Configuration")
{
DPRINTF("%s:%d 'Configuration' expected.\n", filename.c_str(),
tokenizer.getLineNumber());
return NULL;
}
Value* configParamsValue = parser.readValue();
if (configParamsValue == NULL || configParamsValue->getType() != Value::HashType)
{
DPRINTF("%s: Bad configuration file.\n", filename.c_str());
return NULL;
}
Hash* configParams = configParamsValue->getHash();
CelestiaConfig* config = new CelestiaConfig();
configParams->getString("StarDatabase", config->starDatabaseFile);
configParams->getString("StarNameDatabase", config->starNamesFile);
Value* solarSystemsVal = configParams->getValue("SolarSystemCatalogs");
if (solarSystemsVal != NULL)
{
if (solarSystemsVal->getType() != Value::ArrayType)
{
DPRINTF("%s: SolarSystemCatalogs must be an array.\n", filename.c_str());
}
else
{
Array* solarSystems = solarSystemsVal->getArray();
// assert(solarSystems != NULL);
for (Array::iterator iter = solarSystems->begin(); iter != solarSystems->end(); iter++)
{
Value* catalogNameVal = *iter;
// assert(catalogNameVal != NULL);
if (catalogNameVal->getType() == Value::StringType)
{
config->solarSystemFiles.insert(config->solarSystemFiles.end(),
catalogNameVal->getString());
}
else
{
DPRINTF("%s: Solar system catalog name must be a string.\n",
filename.c_str());
}
}
}
}
Value* labelledStarsVal = configParams->getValue("LabelledStars");
if (labelledStarsVal != NULL)
{
if (labelledStarsVal->getType() != Value::ArrayType)
{
DPRINTF("%s: LabelledStars must be an array.\n", filename.c_str());
}
else
{
Array* labelledStars = labelledStarsVal->getArray();
// assert(labelledStars != NULL);
for (Array::iterator iter = labelledStars->begin(); iter != labelledStars->end(); iter++)
{
Value* starNameVal = *iter;
// assert(starNameVal != NULL);
if (starNameVal->getType() == Value::StringType)
{
config->labelledStars.insert(config->labelledStars.end(),
starNameVal->getString());
}
else
{
DPRINTF("%s: Star name must be a string.\n", filename.c_str());
}
}
}
}
delete configParamsValue;
return config;
}

23
src/config.h 100644
View File

@ -0,0 +1,23 @@
// config.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <string>
#include <vector>
struct CelestiaConfig
{
std::string starDatabaseFile;
std::string starNamesFile;
std::vector<std::string> solarSystemFiles;
std::vector<std::string> labelledStars;
};
CelestiaConfig* ReadCelestiaConfig(string filename);

254
src/console.cpp 100644
View File

@ -0,0 +1,254 @@
// console.cpp
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// Text console class for OpenGL
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstdarg>
#include "gl.h"
#include "texfont.h"
#include "console.h"
using namespace std;
Console::Console(int rows, int cols) :
ostream(&sbuf),
nRows(rows),
nColumns(cols),
cursorRow(0),
cursorColumn(0),
font(NULL),
xscale(1.0f),
yscale(1.0f)
{
text = new char*[nRows];
for (int i = 0; i < nRows; i++)
text[i] = new char[nColumns];
clear();
sbuf.setConsole(this);
}
Console::~Console()
{
if (text != NULL)
{
for (int i = 0; i < nRows; i++)
{
if (text[i] != NULL)
delete[] text[i];
}
delete[] text;
}
}
#if 0
Console& Console::operator<<(string s)
{
int len = s.length();
for (int i = 0; i < len; i++)
print(s[i]);
return *this;
}
#endif
void Console::setFont(TexFont* _font)
{
font = _font;
}
TexFont* Console::getFont()
{
return font;
}
void Console::setScale(float _xscale, float _yscale)
{
xscale = _xscale;
yscale = _yscale;
}
void Console::clear()
{
for (int i = 0; i < nRows; i++)
memset(text[i], '\0', nColumns);
}
void Console::home()
{
cursorColumn = 0;
cursorRow = 0;
}
void Console::scrollUp()
{
for (int i = 1; i < nRows; i++)
{
strcpy(text[i - 1], text[i]);
}
memset(text[nRows - 1], '\0', nColumns);
}
void Console::scrollDown()
{
for (int i = nRows - 1; i > 0; i++)
{
strcpy(text[i], text[i - 1]);
}
memset(text[0], '\0', nColumns);
}
void Console::cursorRight()
{
if (cursorColumn < nColumns - 1)
cursorColumn++;
}
void Console::cursorLeft()
{
if (cursorColumn > 0)
cursorColumn--;
}
void Console::CR()
{
cursorColumn = 0;
}
void Console::LF()
{
cursorRow++;
if (cursorRow == nRows)
{
cursorRow--;
scrollUp();
}
}
void Console::setCharAt(char c, int row, int col)
{
if (row >= 0 && row < nRows && col >= 0 && col < nColumns)
text[row][col] = c;
}
void Console::print(char c)
{
switch (c)
{
case '\n':
CR();
LF();
break;
case '\r':
CR();
break;
case '\b':
cursorLeft();
break;
default:
text[cursorRow][cursorColumn] = c;
cursorRight();
break;
}
}
void Console::print(char* s)
{
while (*s != '\0')
print(*s++);
}
void Console::printf(char* format, ...)
{
va_list args;
va_start(args, format);
char buf[1024];
vsprintf(buf, format, args);
print(buf);
va_end(args);
}
void Console::render()
{
float width = 1.8f;
float height = 1.8f;
float top = 0.9f;
float left = -0.9f;
float aspectRatio = 4.0f / 3.0f;
float charHeight = height / (float) nRows;
float charWidth = charHeight / aspectRatio / 2.0f;
float scale = 0.005f;
if (font == NULL)
return;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, font->texobj);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(-1, 0.9f, -1);
glScalef(xscale, yscale, 1);
for (int i = 0; i < nRows; i++)
{
float x = left;
char* s = text[i];
glPushMatrix();
while (*s != '\0')
{
txfRenderGlyph(font, *s);
s++;
}
glPopMatrix();
glTranslatef(0, -(1 + font->max_ascent + font->max_descent), 0);
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
ConsoleStreamBuf::setConsole(Console* c)
{
console = c;
}
int ConsoleStreamBuf::overflow(int c)
{
if (console != NULL)
console->print((char) c);
return c;
}

95
src/console.h 100644
View File

@ -0,0 +1,95 @@
// console.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Text console class for OpenGL. The console supports both printf
// and C++ operator style mechanisms for output.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include <string>
#include <iostream>
#include "gl.h"
#include "texfont.h"
using namespace std;
class Console;
// Custom streambuf class to support C++ operator style output. The
// output is completely unbuffered so that it can coexist with printf
// style output which the Console class also supports.
class ConsoleStreamBuf : public std::streambuf
{
public:
ConsoleStreamBuf() : console(NULL) { setbuf(0, 0); };
setConsole(Console*);
int overflow(int c = EOF);
private:
Console* console;
};
class Console : public std::ostream
{
public:
Console(int rows, int cols);
~Console();
void setFont(TexFont*);
TexFont* getFont();
void setScale(float, float);
void render();
void clear();
void home();
void scrollUp();
void scrollDown();
void cursorRight();
void cursorLeft();
void CR();
void LF();
inline void setChar(char c);
void setCharAt(char c, int row, int col);
void print(char);
void print(char*);
void printf(char*, ...);
// Console& operator<<(string);
private:
int nRows;
int nColumns;
char** text;
TexFont* font;
int cursorRow;
int cursorColumn;
float xscale, yscale;
ConsoleStreamBuf sbuf;
};
void Console::setChar(char c)
{
text[cursorRow][cursorColumn] = c;
}
#endif // _CONSOLE_H_

View File

@ -0,0 +1,165 @@
// constellation.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iostream>
#include "celestia.h"
#include "constellation.h"
using namespace std;
struct Constellation_s {
char *name;
char *gen;
char *abbr;
};
static struct Constellation_s constellationInfo[] = {
{ "Aries", "Arietis", "Ari" },
{ "Taurus", "Tauri", "Tau" },
{ "Gemini", "Geminorum", "Gem" },
{ "Cancer", "Cancri", "Cnc" },
{ "Leo", "Leonis", "Leo" },
{ "Virgo", "Virginis", "Vir" },
{ "Libra", "Librae", "Lib" },
{ "Scorpius", "Scorpii", "Sco" },
{ "Sagittarius", "Sagittarii", "Sgr" },
{ "Capricornus", "Capricornii", "Cap" },
{ "Aquarius", "Aquarii", "Aqr" },
{ "Pisces", "Piscium", "Psc" },
{ "Ursa Major", "Ursae Majoris", "UMa" },
{ "Ursa Minor", "Ursae Minoris", "UMi" },
{ "Bootes", "Bootis", "Boo" },
{ "Orion", "Orionis", "Ori" },
{ "Canis Major", "Canis Majoris", "CMa" },
{ "Canis Minor", "Canis Minoris", "CMi" },
{ "Lepus", "Leporis", "Lep" },
{ "Perseus", "Persei", "Per" },
{ "Andromeda", "Andromedae", "And" },
{ "Cassiopeia", "Cassiopeiae", "Cas" },
{ "Cepheus", "Cephei", "Cep" },
{ "Cetus", "Ceti", "Cet" },
{ "Pegasus", "Pegasi", "Peg" },
{ "Carina", "Carinae", "Car" },
{ "Puppis", "Puppis", "Pup" },
{ "Vela", "Velorum", "Vel" },
{ "Hercules", "Herculis", "Her" },
{ "Hydra", "Hydrae", "Hya" },
{ "Centaurus", "Centauri", "Cen" },
{ "Lupus", "Lupi", "Lup" },
{ "Ara", "Arae", "Ara" },
{ "Ophiuchus", "Ophiuchi", "Oph" },
{ "Serpens", "Serpentis", "Ser" },
{ "Aquila", "Aquilae", "Aql" },
{ "Auriga", "Aurigae", "Aur" },
{ "Corona Australis", "Coronae Australis", "CrA" },
{ "Corona Borealias", "Coronae Borealis", "CrB" },
{ "Corvus", "Corvi", "Crv" },
{ "Crater", "Crateris", "Crt" },
{ "Cygnus", "Cyngi", "Cyg" },
{ "Delphinus", "Delphini", "Del" },
{ "Draco", "Draconis", "Dra" },
{ "Equuleus", "Equulei", "Equ" },
{ "Eridanus", "Eridani", "Eri" },
{ "Lyra", "Lyrae", "Lyr" },
{ "Piscis Austrinus", "Piscis Austrini", "PsA" },
{ "Sagitta", "Sagittae", "Sge" },
{ "Triangulum", "Trianguli", "Tri" },
{ "Antlia", "Antliae", "Ant" },
{ "Apus", "Apodis", "Aps" },
{ "Caelum", "Caeli", "Cae" },
{ "Camelopardalis", "Camelopardalis", "Cam" },
{ "Canes Venatici", "Canum Venaticorum", "CVn" },
{ "Chamaeleon", "Chamaeleontis", "Cha" },
{ "Circinus", "Circini", "Cir" },
{ "Columba", "Columbae", "Col" },
{ "Coma Berenices", "Comae Berenices", "Com" },
{ "Crux", "Crucis", "Cru" },
{ "Dorado", "Doradus", "Dor" },
{ "Fornax", "Fornacis", "For" },
{ "Grus", "Gruis", "Gru" },
{ "Horologium", "Horologii", "Hor" },
{ "Hydrus", "Hydri", "Hyi" },
{ "Indus", "Indi", "Ind" },
{ "Lacerta", "Lacertae", "Lac" },
{ "Leo Minor", "Leonis Minoris", "LMi" },
{ "Lynx", "Lyncis", "Lyn" },
{ "Microscopium", "Microscopii", "Mic" },
{ "Monoceros", "Monocerotis", "Mon" },
{ "Mensa", "Mensae", "Men" },
{ "Musca", "Muscae", "Mus" },
{ "Norma", "Normae", "Nor" },
{ "Octans", "Octantis", "Oct" },
{ "Pavo", "Pavonis", "Pav" },
{ "Phoenix", "Phoenicis", "Phe" },
{ "Pictor", "Pictoris", "Pic" },
{ "Pyxis", "Pyxidis", "Pyx" },
{ "Reticulum", "Reticuli", "Ret" },
{ "Sculptor", "Sculptoris", "Scl" },
{ "Scutum", "Scuti", "Sct" },
{ "Sextans", "Sextantis", "Sex" },
{ "Telescopium", "Telescopii", "Tel" },
{ "Triangulum Australe", "Trianguli Australis", "TrA" },
{ "Tucana", "Tucanae", "Tuc" },
{ "Volans", "Volantis", "Vol" },
{ "Vulpecula", "Vulpeculae", "Vul" }
};
static Constellation **constellations = NULL;
Constellation::Constellation(char *_name, char *_genitive, char *_abbrev)
{
name = string(_name);
genitive = string(_genitive);
abbrev = string(_abbrev);
}
Constellation *Constellation::getConstellation(unsigned int n)
{
if (constellations == NULL)
initialize();
if (constellations == NULL ||
n >= sizeof(constellationInfo) / sizeof(constellationInfo[0]))
return NULL;
else
return constellations[n];
}
string Constellation::getName()
{
return name;
}
string Constellation::getGenitive()
{
return genitive;
}
string Constellation::getAbbreviation()
{
return abbrev;
}
void Constellation::initialize()
{
int nConstellations = sizeof(constellationInfo) / sizeof(constellationInfo[0]);
constellations = new Constellation* [nConstellations];
if (constellations != NULL)
{
for (int i = 0; i < nConstellations; i++)
{
constellations[i] = new Constellation(constellationInfo[i].name,
constellationInfo[i].gen,
constellationInfo[i].abbr);
}
}
}

View File

@ -0,0 +1,34 @@
// constellation.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _CONSTELLATION_H_
#define _CONSTELLATION_H_
#include <string>
class Constellation
{
public:
static Constellation *getConstellation(unsigned int);
std::string getName();
std::string getGenitive();
std::string getAbbreviation();
private:
Constellation(char *_name, char *_genitive, char *_abbrev);
static void initialize();
std::string name;
std::string genitive;
std::string abbrev;
};
#endif // _CONSTELLATION_H_

42
src/debug.cpp 100644
View File

@ -0,0 +1,42 @@
// debug.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifdef _MSC_VER
#include <windows.h>
#endif
#include <stdio.h>
#include <cstdarg>
void DebugPrint(char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef _MSC_VER
char buf[1024];
vsprintf(buf, format, args);
OutputDebugString(buf);
#else
vfprintf(stderr, format, args);
#endif
va_end(args);
}
void Log(char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
}

44
src/dispmap.cpp 100644
View File

@ -0,0 +1,44 @@
// dispmap.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "dispmap.h"
DisplacementMap::DisplacementMap(int w, int h) :
width(w), height(h), disp(NULL)
{
disp = new float[width * height];
}
DisplacementMap::~DisplacementMap()
{
if (disp != NULL)
delete[] disp;
}
void DisplacementMap::clear()
{
int size = width * height;
for (int i = 0; i < size; i++)
disp[i] = 0.0f;
}
void DisplacementMap::generate(DisplacementMapFunc func, void* info)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
disp[i * width + j] = func((float) j / (float) width,
(float) i / (float) height, info);
}
}
}

50
src/dispmap.h 100644
View File

@ -0,0 +1,50 @@
// dispmap.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _DISPMAP_H_
#define _DISPMAP_H_
#include <string>
#include "vecmath.h"
typedef float (*DisplacementMapFunc)(float, float, void*);
class DisplacementMap
{
public:
DisplacementMap(int w, int h);
~DisplacementMap();
int getWidth() const { return width; };
int getHeight() const { return height; };
inline float getDisplacement(int x, int y) const;
inline void setDisplacement(int x, int y, float d);
void generate(DisplacementMapFunc func, void* info = NULL);
void clear();
private:
int width;
int height;
float* disp;
};
// extern DisplacementMap* LoadDisplacementMap(std::string filename);
float DisplacementMap::getDisplacement(int x, int y) const
{
return disp[y * width + x];
}
void DisplacementMap::setDisplacement(int x, int y, float d)
{
disp[y * width + x] = d;
}
#endif // _DISPMAP_H_

62
src/filetype.cpp 100644
View File

@ -0,0 +1,62 @@
// filetype.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cctype>
#include "filetype.h"
using namespace std;
static const string JPEGExt(".jpg");
static const string BMPExt(".bmp");
static const string TargaExt(".tga");
static const string ThreeDSExt(".3ds");
static const string CelestiaTextureExt(".ctx");
static const string CelestiaMeshExt(".cms");
static int compareIgnoringCase(const string& s1, const string& s2)
{
string::const_iterator i1 = s1.begin();
string::const_iterator i2 = s2.begin();
while (i1 != s1.end() && i2 != s2.end())
{
if (toupper(*i1) != toupper(*i2))
return (toupper(*i1) < toupper(*i2)) ? -1 : 1;
++i1;
++i2;
}
return s2.size() - s1.size();
}
ContentType DetermineFileType(const string& filename)
{
int extPos = filename.length() - 4;
if (extPos < 0)
extPos = 0;
string ext = string(filename, extPos, 4);
if (compareIgnoringCase(JPEGExt, ext) == 0)
return Content_JPEG;
else if (compareIgnoringCase(BMPExt, ext) == 0)
return Content_BMP;
else if (compareIgnoringCase(TargaExt, ext) == 0)
return Content_Targa;
else if (compareIgnoringCase(ThreeDSExt, ext) == 0)
return Content_3DStudio;
else if (compareIgnoringCase(CelestiaTextureExt, ext) == 0)
return Content_CelestiaTexture;
else if (compareIgnoringCase(CelestiaMeshExt, ext) == 0)
return Content_CelestiaMesh;
else
return Content_Unknown;
}

28
src/filetype.h 100644
View File

@ -0,0 +1,28 @@
// filetype.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _FILETYPE_H_
#define _FILETYPE_H_
#include <string>
enum ContentType {
Content_JPEG,
Content_BMP,
Content_GIF,
Content_Targa,
Content_CelestiaTexture,
Content_3DStudio,
Content_CelestiaMesh,
Content_Unknown
};
ContentType DetermineFileType(const std::string& filename);
#endif // _FILETYPE_H_

32
src/gl.h 100644
View File

@ -0,0 +1,32 @@
// gl.h
//
// Why is this file necessary? Because Microsoft requires us to include
// windows.h before including the GL headers, even though GL is a
// cross-platform API. So, we encapsulate the resulting ifdef nonsense
// in this file.
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _GL_H_
#define _GL_H_
#ifdef _MSC_VER
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#endif // _MSC_VER
#include <GL/gl.h>
#include <GL/glu.h>
#endif // _GL_H_

228
src/glext.cpp 100644
View File

@ -0,0 +1,228 @@
// glext.cpp
#include <string.h>
#include "gl.h"
#include "glext.h"
// ARB_texture_compression
PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB;
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB;
PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB;
PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB;
PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB;
// ARB_multitexture command function pointers
PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB;
PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
// NV_register_combiners command function pointers
PFNGLCOMBINERPARAMETERFVNVPROC glCombinerParameterfvNV;
PFNGLCOMBINERPARAMETERIVNVPROC glCombinerParameterivNV;
PFNGLCOMBINERPARAMETERFNVPROC glCombinerParameterfNV;
PFNGLCOMBINERPARAMETERINVPROC glCombinerParameteriNV;
PFNGLCOMBINERINPUTNVPROC glCombinerInputNV;
PFNGLCOMBINEROUTPUTNVPROC glCombinerOutputNV;
PFNGLFINALCOMBINERINPUTNVPROC glFinalCombinerInputNV;
PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC glGetCombinerInputParameterfvNV;
PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC glGetCombinerInputParameterivNV;
PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC glGetCombinerOutputParameterfvNV;
PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC glGetCombinerOutputParameterivNV;
PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC glGetFinalCombinerInputParameterfvNV;
PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC glGetFinalCombinerInputParameterivNV;
// EXT_paletted_texture command function pointers
PFNGLCOLORTABLEEXTPROC glColorTableEXT;
// WGL_EXT_swap_control command function pointers
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
// extern void Alert(const char *szFormat, ...);
void Alert(const char *szFormat, ...)
{
}
#if 0
// Check for required extensions and initialize them if present
bool InitGLExtensions(void)
{
#if 0
if (!extensionSupported("GL_EXT_bgra")) {
Alert("Required OpenGL extension GL_EXT_bgra not supported");
return false;
}
#endif
if (!extensionSupported("GL_ARB_multitexture")) {
Alert("Required OpenGL extension GL_ARB_multitexture not supported");
return false;
}
#if 0
if (!extensionSupported("GL_EXT_texture_env_combine")) {
Alert("Required OpenGL extension GL_EXT_texture_env_combine not supported");
return false;
}
if (!extensionSupported("GL_NV_register_combiners")) {
Alert("Required OpenGL extension GL_NV_register_combiners not supported");
return false;
}
if (!extensionSupported("GL_EXT_texture_cube_map")) {
Alert("Required OpenGL extension GL_EXT_texture_cube_map not supported");
return false;
}
if (!extensionSupported("GL_EXT_separate_specular_color")) {
Alert("Required OpenGL extension GL_EXT_separate_specular_color not supported");
return false;
}
if (!extensionSupported("WGL_EXT_swap_control")) {
Alert("Required OpenGL extension WGL_EXT_swap_control not supported");
return false;
}
#endif
initMultiTexture();
#if 0
initRegisterCombiners();
initSwapControl();
#endif
return true;
}
#endif
// ARB_multitexture
void InitExtMultiTexture()
{
glMultiTexCoord2iARB =
(PFNGLMULTITEXCOORD2IARBPROC) wglGetProcAddress("glMultiTexCoord2iARB");
glMultiTexCoord2fARB =
(PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB =
(PFNGLMULTITEXCOORD3FARBPROC) wglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord3fvARB =
(PFNGLMULTITEXCOORD3FVARBPROC) wglGetProcAddress("glMultiTexCoord3fvARB");
glActiveTextureARB =
(PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB =
(PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
}
// ARB_texture_compression
void InitExtTextureCompression()
{
glCompressedTexImage3DARB =
(PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)
wglGetProcAddress("glCompressedTexImage3DARB");
glCompressedTexImage2DARB =
(PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)
wglGetProcAddress("glCompressedTexImage2DARB");
glCompressedTexImage1DARB =
(PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)
wglGetProcAddress("glCompressedTexImage1DARB");
glCompressedTexSubImage3DARB =
(PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)
wglGetProcAddress("glCompressedTexSubImage3DARB");
glCompressedTexSubImage2DARB =
(PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)
wglGetProcAddress("glCompressedTexSubImage2DARB");
glCompressedTexSubImage1DARB =
(PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)
wglGetProcAddress("glCompressedTexSubImage1DARB");
}
// NV_register_combiners
void InitExtRegisterCombiners()
{
/* Retrieve all NV_register_combiners routines. */
glCombinerParameterfvNV =
(PFNGLCOMBINERPARAMETERFVNVPROC)
wglGetProcAddress("glCombinerParameterfvNV");
glCombinerParameterivNV =
(PFNGLCOMBINERPARAMETERIVNVPROC)
wglGetProcAddress("glCombinerParameterivNV");
glCombinerParameterfNV =
(PFNGLCOMBINERPARAMETERFNVPROC)
wglGetProcAddress("glCombinerParameterfNV");
glCombinerParameteriNV =
(PFNGLCOMBINERPARAMETERINVPROC)
wglGetProcAddress("glCombinerParameteriNV");
glCombinerInputNV =
(PFNGLCOMBINERINPUTNVPROC)
wglGetProcAddress("glCombinerInputNV");
glCombinerOutputNV =
(PFNGLCOMBINEROUTPUTNVPROC)
wglGetProcAddress("glCombinerOutputNV");
glFinalCombinerInputNV =
(PFNGLFINALCOMBINERINPUTNVPROC)
wglGetProcAddress("glFinalCombinerInputNV");
glGetCombinerInputParameterfvNV =
(PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)
wglGetProcAddress("glGetCombinerInputParameterfvNV");
glGetCombinerInputParameterivNV =
(PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)
wglGetProcAddress("glGetCombinerInputParameterivNV");
glGetCombinerOutputParameterfvNV =
(PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)
wglGetProcAddress("glGetCombinerOutputParameterfvNV");
glGetCombinerOutputParameterivNV =
(PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)
wglGetProcAddress("glGetCombinerOutputParameterivNV");
glGetFinalCombinerInputParameterfvNV =
(PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)
wglGetProcAddress("glGetFinalCombinerInputParameterfvNV");
glGetFinalCombinerInputParameterivNV =
(PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)
wglGetProcAddress("glGetFinalCombinerInputParameterivNV");
}
void InitExtPalettedTexture()
{
// glColorTableEXT = (void *) wglGetProcAddress("glColorTableEXT");
}
void InitExtSwapControl()
{
wglSwapIntervalEXT =
(PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
wglGetSwapIntervalEXT =
(PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress("wglGetSwapIntervalEXT");
}
bool ExtensionSupported(char *ext)
{
char *extensions = (char *) glGetString(GL_EXTENSIONS);
if (extensions == NULL)
return false;
int len = strlen(ext);
for (;;) {
if (strncmp(extensions, ext, len) == 0)
return true;
extensions = strchr(extensions, ' ');
if (extensions != NULL)
extensions++;
else
break;
}
return false;
}

318
src/glext.h 100644
View File

@ -0,0 +1,318 @@
/* glext.h */
#ifndef _GLEXT_H_
#define _GLEXT_H_
/* EXT_rescale_normal defines from <GL/gl.h> */
#ifndef GL_EXT_rescale_normal
#define GL_RESCALE_NORMAL_EXT 0x803A
#endif
/* EXT_texture_edge_clamp defines from <GL/gl.h> */
#ifndef GL_EXT_texture_edge_clamp
#define GL_CLAMP_TO_EDGE_EXT 0x812F
#endif
/* EXT_bgra defines from <GL/gl.h> */
#ifndef GL_EXT_bgra
#define GL_BGR_EXT 0x80E0
#define GL_BGRA_EXT 0x80E1
#endif
/* GL_ARB_texture_compression */
#ifndef GL_ARB_texture_compression
#define GL_ARB_texture_compression 1
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
#define GL_TEXTURE_IMAGE_SIZE_ARB 0x86A0
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
#if 0
extern void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
extern void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
extern void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
extern void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
extern void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
extern void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
extern void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, void *);
#endif /* GL_GLEXT_PROTOTYPES */
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img);
#endif
/* GL_EXT_texture_compression_s3tc */
#ifndef GL_EXT_texture_compression_s3tc
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
/* ARB_multitexture defines and prototypes from <GL/gl.h> */
#ifndef GL_ARB_multitexture
#define GL_ACTIVE_TEXTURE_ARB 0x84E0
#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target);
typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target);
#endif
/* EXT_texture_cube_map defines from <GL/gl.h> */
#ifndef GL_EXT_texture_cube_map
#define GL_NORMAL_MAP_EXT 0x8511
#define GL_REFLECTION_MAP_EXT 0x8512
#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
#endif
/* EXT_separate_specular_color defines from <GL/gl.h> */
#ifndef GL_EXT_separate_specular_color
#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
#define GL_SINGLE_COLOR_EXT 0x81F9
#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
#endif
/* EXT_texture_env_combine defines from <GL/gl.h> */
#ifndef GL_EXT_texture_env_combine
// Accepted by the <params> parameter of TexEnvf, TexEnvi, TexEnvfv,
// and TexEnviv when the <pname> parameter value is TEXTURE_ENV_MODE
#define GL_COMBINE_EXT 0x8570
// Accepted by the <pname> parameter of TexEnvf, TexEnvi, TexEnvfv,
// and TexEnviv when the <target> parameter value is TEXTURE_ENV
#define GL_COMBINE_RGB_EXT 0x8571
#define GL_COMBINE_ALPHA_EXT 0x8572
#define GL_SOURCE0_RGB_EXT 0x8580
#define GL_SOURCE1_RGB_EXT 0x8581
#define GL_SOURCE2_RGB_EXT 0x8582
#define GL_SOURCE0_ALPHA_EXT 0x8588
#define GL_SOURCE1_ALPHA_EXT 0x8589
#define GL_SOURCE2_ALPHA_EXT 0x858A
#define GL_OPERAND0_RGB_EXT 0x8590
#define GL_OPERAND1_RGB_EXT 0x8591
#define GL_OPERAND2_RGB_EXT 0x8592
#define GL_OPERAND0_ALPHA_EXT 0x8598
#define GL_OPERAND1_ALPHA_EXT 0x8599
#define GL_OPERAND2_ALPHA_EXT 0x859A
#define GL_RGB_SCALE_EXT 0x8573
// Accepted by the <params> parameter of TexEnvf, TexEnvi, TexEnvfv,
// and TexEnviv when the <pname> parameter value is COMBINE_RGB_EXT
// or COMBINE_ALPHA_EXT
#define GL_ADD_SIGNED_EXT 0x8574
#define GL_INTERPOLATE_EXT 0x8575
// Accepted by the <params> parameter of TexEnvf, TexEnvi, TexEnvfv,
// and TexEnviv when the <pname> parameter value is SOURCE0_RGB_EXT,
// SOURCE1_RGB_EXT, SOURCE2_RGB_EXT, SOURCE0_ALPHA_EXT,
// SOURCE1_ALPHA_EXT, or SOURCE2_ALPHA_EXT
#define GL_CONSTANT_EXT 0x8576
#define GL_PRIMARY_COLOR_EXT 0x8577
#define GL_PREVIOUS_EXT 0x8578
#endif // GL_EXT_texture_env_combine
/* NV_register_combiners defines and prototypes from <GL/gl.h> */
#ifndef GL_NV_register_combiners
#define GL_REGISTER_COMBINERS_NV 0x8522
#define GL_COMBINER0_NV 0x8550
#define GL_COMBINER1_NV 0x8551
#define GL_COMBINER2_NV 0x8552
#define GL_COMBINER3_NV 0x8553
#define GL_COMBINER4_NV 0x8554
#define GL_COMBINER5_NV 0x8555
#define GL_COMBINER6_NV 0x8556
#define GL_COMBINER7_NV 0x8557
#define GL_VARIABLE_A_NV 0x8523
#define GL_VARIABLE_B_NV 0x8524
#define GL_VARIABLE_C_NV 0x8525
#define GL_VARIABLE_D_NV 0x8526
#define GL_VARIABLE_E_NV 0x8527
#define GL_VARIABLE_F_NV 0x8528
#define GL_VARIABLE_G_NV 0x8529
/* GL_ZERO */
#define GL_CONSTANT_COLOR0_NV 0x852A
#define GL_CONSTANT_COLOR1_NV 0x852B
/* GL_FOG */
#define GL_PRIMARY_COLOR_NV 0x852C
#define GL_SECONDARY_COLOR_NV 0x852D
#define GL_SPARE0_NV 0x852E
#define GL_SPARE1_NV 0x852F
/* GL_TEXTURE0_ARB */
/* GL_TEXTURE1_ARB */
#define GL_UNSIGNED_IDENTITY_NV 0x8536
#define GL_UNSIGNED_INVERT_NV 0x8537
#define GL_EXPAND_NORMAL_NV 0x8538
#define GL_EXPAND_NEGATE_NV 0x8539
#define GL_HALF_BIAS_NORMAL_NV 0x853A
#define GL_HALF_BIAS_NEGATE_NV 0x853B
#define GL_SIGNED_IDENTITY_NV 0x853C
#define GL_SIGNED_NEGATE_NV 0x853D
#define GL_E_TIMES_F_NV 0x8531
#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
/* GL_NONE */
#define GL_SCALE_BY_TWO_NV 0x853E
#define GL_SCALE_BY_FOUR_NV 0x853F
#define GL_SCALE_BY_ONE_HALF_NV 0x8540
#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
#define GL_DISCARD_NV 0x8530
#define GL_COMBINER_INPUT_NV 0x8542
#define GL_COMBINER_MAPPING_NV 0x8543
#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
#define GL_COMBINER_MUX_SUM_NV 0x8547
#define GL_COMBINER_SCALE_NV 0x8548
#define GL_COMBINER_BIAS_NV 0x8549
#define GL_COMBINER_AB_OUTPUT_NV 0x854A
#define GL_COMBINER_CD_OUTPUT_NV 0x854B
#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
#define GL_COLOR_SUM_CLAMP_NV 0x854F
typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
typedef void (APIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
typedef void (APIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
typedef void (APIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
typedef void (APIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
typedef void (APIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
#endif
/* EXT_paletted_texture defines and prototypes from <GL/gl.h> */
#ifndef GL_EXT_paletted_texture
#define GL_COLOR_INDEX1_EXT 0x80E2
#define GL_COLOR_INDEX2_EXT 0x80E3
#define GL_COLOR_INDEX4_EXT 0x80E4
#define GL_COLOR_INDEX8_EXT 0x80E5
#define GL_COLOR_INDEX12_EXT 0x80E6
#define GL_COLOR_INDEX16_EXT 0x80E7
typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table);
PFNGLCOLORTABLEEXTPROC glColorTableEXT;
#endif
/* WGL_EXT_swap_control defines and prototypes from <GL/gl.h> */
#ifndef WGL_EXT_swap_control
typedef int (APIENTRY * PFNWGLSWAPINTERVALEXTPROC) (int);
typedef int (APIENTRY * PFNWGLGETSWAPINTERVALEXTPROC) (void);
#endif
/* OpenGL 1.2 defines and prototypes from <GL/gl.h> */
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
#ifdef _WIN32
/* ARB_texture_compression command function pointers */
extern PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB;
extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
extern PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB;
extern PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB;
extern PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB;
extern PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB;
/* ARB_multitexture command function pointers */
extern PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB;
extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
extern PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB;
extern PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB;
extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
/* NV_register_combiners command function pointers */
extern PFNGLCOMBINERPARAMETERFVNVPROC glCombinerParameterfvNV;
extern PFNGLCOMBINERPARAMETERIVNVPROC glCombinerParameterivNV;
extern PFNGLCOMBINERPARAMETERFNVPROC glCombinerParameterfNV;
extern PFNGLCOMBINERPARAMETERINVPROC glCombinerParameteriNV;
extern PFNGLCOMBINERINPUTNVPROC glCombinerInputNV;
extern PFNGLCOMBINEROUTPUTNVPROC glCombinerOutputNV;
extern PFNGLFINALCOMBINERINPUTNVPROC glFinalCombinerInputNV;
extern PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC glGetCombinerInputParameterfvNV;
extern PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC glGetCombinerInputParameterivNV;
extern PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC glGetCombinerOutputParameterfvNV;
extern PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC glGetCombinerOutputParameterivNV;
extern PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC glGetFinalCombinerInputParameterfvNV;
extern PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC glGetFinalCombinerInputParameterivNV;
/* EXT_paletted_texture command function pointers */
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
/* WGL_EXT_swap_control command function pointers */
extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
#endif
extern bool ExtensionSupported(char *ext);
extern void InitExtRegisterCombiners();
extern void InitExtMultiTexture();
extern void InitExtPalettedTextures();
extern void InitExtSwapControl();
extern void InitExtTextureCompression();
#endif // _GLEXT_H_

152
src/gui.cpp 100644
View File

@ -0,0 +1,152 @@
// gui.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "gl.h"
#include "gui.h"
using namespace std;
using namespace gui;
/**** GraphicsContext ****/
GraphicsContext::GraphicsContext() :
font(NULL)
{
}
TexFont* GraphicsContext::getFont() const
{
return font;
}
void GraphicsContext::setFont(TexFont* _font)
{
font = _font;
}
/**** Component ****/
Component::Component() :
position(0, 0),
size(0, 0),
parent(NULL)
{
}
Point2f Component::getPosition() const
{
return position;
}
Vec2f Component::getSize() const
{
return size;
}
void Component::reshape(Point2f _position, Vec2f _size)
{
position = _position;
size = _size;
}
Component* Component::getParent() const
{
return parent;
}
void Component::setParent(Component* c)
{
parent = c;
}
/**** Container ****/
Container::Container() : Component()
{
}
int Container::getComponentCount() const
{
return components.size();
}
Component* Container::getComponent(int n) const
{
if (n >= 0 && n < components.size())
return components[n];
else
return NULL;
}
void Container::addComponent(Component* c)
{
// ASSERT(c->getParent() == NULL)
components.insert(components.end(), c);
c->setParent(this);
}
void Container::render(GraphicsContext& gc)
{
glPushMatrix();
glTranslatef(getPosition().x, getPosition().y, 0);
vector<Component*>::iterator iter = components.begin();
while (iter != components.end())
{
(*iter)->render(gc);
iter++;
}
glPopMatrix();
}
/**** Button ****/
Button::Button(string _label) : label(_label)
{
}
string Button::getLabel() const
{
return label;
}
void Button::setLabel(string _label)
{
label = _label;
}
void Button::render(GraphicsContext& gc)
{
glBegin(GL_LINE_LOOP);
Point2f pos = getPosition();
Vec2f sz = getSize();
glVertex3f(pos.x, pos.y, 0);
glVertex3f(pos.x + sz.x, pos.y, 0);
glVertex3f(pos.x + sz.x, pos.y + sz.y, 0);
glVertex3f(pos.x, pos.y + sz.y, 0);
glEnd();
int maxAscent = 0, maxDescent = 0, stringWidth = 0;
txfGetStringMetrics(gc.getFont(), label,
stringWidth, maxAscent, maxDescent);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gc.getFont()->texobj);
glPushMatrix();
glTranslatef(pos.x + (sz.x - stringWidth) / 2,
pos.y + (sz.y - (maxDescent)) / 2,
0);
txfRenderString(gc.getFont(), label);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}

84
src/gui.h 100644
View File

@ -0,0 +1,84 @@
// gui.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _GUI_H_
#define _GUI_H_
#include <vector>
#include <string>
#include "vecmath.h"
#include "texfont.h"
namespace gui
{
class GraphicsContext
{
public:
GraphicsContext();
TexFont* getFont() const;
void setFont(TexFont*);
private:
TexFont* font;
};
class Component
{
public:
Component();
Point2f getPosition() const;
Vec2f getSize() const;
void reshape(Point2f, Vec2f);
Component* getParent() const;
virtual void render(GraphicsContext&) = 0;
// protected:
void setParent(Component*);
private:
Point2f position;
Vec2f size;
Component* parent;
};
class Container : public Component
{
public:
Container();
int getComponentCount() const;
Component* getComponent(int) const;
void addComponent(Component*);
void render(GraphicsContext&);
private:
std::vector<Component*> components;
};
class Button : public Component
{
public:
Button(std::string);
std::string getLabel() const;
void setLabel(std::string);
void render(GraphicsContext&);
private:
std::string label;
};
};
#endif // _GUI_H_

115
src/mathlib.h 100644
View File

@ -0,0 +1,115 @@
// mathlib.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _MATHLIB_H_
#define _MATHLIB_H_
#include <cmath>
#include <stdlib.h>
#define PI 3.14159265358979323846
template<class T> class Math
{
public:
static inline void sincos(T, T&, T&);
static inline T frand();
static inline T sfrand();
static inline T lerp(T t, T a, T b);
static inline T clamp(T t);
private:
// This class is static and should not be instantiated
Math() {};
};
typedef Math<float> Mathf;
typedef Math<double> Mathd;
template<class T> T degToRad(T d)
{
return d / 180 * static_cast<T>(PI);
}
template<class T> T radToDeg(T r)
{
return r * 180 / static_cast<T>(PI);
}
template<class T> T abs(T x)
{
return (x < 0) ? -x : x;
}
template<class T> T square(T x)
{
return x * x;
}
template<class T> T clamp(T x)
{
if (x < 0)
return 0;
else if (x > 1)
return 1;
else
return x;
}
template<class T> T circleArea(T r)
{
return (T) PI * r * r;
}
template<class T> T sphereArea(T r)
{
return 4 * (T) PI * r * r;
}
template<class T> void Math<T>::sincos(T angle, T& s, T& c)
{
s = (T) sin(angle);
c = (T) cos(angle);
}
// return a random float in [0, 1]
template<class T> T Math<T>::frand()
{
return (T) (rand() & 0x7fff) / (T) 32767;
}
// return a random float in [-1, 1]
template<class T> T Math<T>::sfrand()
{
return (T) (rand() & 0x7fff) / (T) 32767 * 2 - 1;
}
template<class T> T Math<T>::lerp(T t, T a, T b)
{
return a + t * (b - a);
}
// return t clamped to [0, 1]
template<class T> T Math<T>::clamp(T t)
{
if (t < 0)
return 0;
else if (t > 1)
return 1;
else
return t;
}
#endif // _MATHLIB_H_

20
src/mesh.h 100644
View File

@ -0,0 +1,20 @@
// mesh.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _MESH_H_
#define _MESH_H_
class Mesh
{
public:
virtual void render() = 0;
};
#endif // _MESH_H_

160
src/meshmanager.cpp 100644
View File

@ -0,0 +1,160 @@
// meshmanager.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iostream>
#include <fstream>
#include "celestia.h"
#include "mathlib.h"
#include "parser.h"
#include "3dsread.h"
#include "3dsmesh.h"
#include "spheremesh.h"
#include "perlin.h"
#include "filetype.h"
#include "meshmanager.h"
using namespace std;
static Mesh* LoadCelestiaMesh(const string& filename);
MeshManager::~MeshManager()
{
// TODO: Clean up
}
bool MeshManager::find(string name, Mesh** mesh)
{
return findResource(name, (void**) mesh);
}
Mesh* MeshManager::load(string name)
{
ContentType fileType = DetermineFileType(name);
Mesh* mesh = NULL;
if (fileType == Content_3DStudio)
{
Mesh3DS* mesh3 = NULL;
M3DScene* scene = Read3DSFile(baseDir + '\\' + name);
if (scene != NULL)
{
mesh3 = new Mesh3DS(*scene);
mesh3->normalize();
delete scene;
}
mesh = mesh3;
}
else if (fileType == Content_CelestiaMesh)
{
mesh = LoadCelestiaMesh(baseDir + '\\' + name);
}
addResource(name, (void*) mesh);
return mesh;
}
struct NoiseMeshParameters
{
Vec3f size;
Vec3f offset;
float featureHeight;
float octaves;
float slices;
float rings;
};
static float NoiseDisplacementFunc(float u, float v, void* info)
{
float theta = u * (float) PI * 2;
float phi = (v - 0.5f) * (float) PI;
float x = (float) (cos(phi) * cos(theta));
float y = (float) sin(phi);
float z = (float) (cos(phi) * sin(theta));
// assert(info != NULL);
NoiseMeshParameters* params = (NoiseMeshParameters*) info;
return fractalsum(Point3f(x, y, z) + params->offset,
(int) params->octaves) * params->featureHeight;
}
Mesh* LoadCelestiaMesh(const string& filename)
{
ifstream meshFile(filename.c_str(), ios::in);
if (!meshFile.good())
{
DPRINTF("Error opening mesh file: %s\n", filename.c_str());
return NULL;
}
Tokenizer tokenizer(&meshFile);
Parser parser(&tokenizer);
if (tokenizer.nextToken() != Tokenizer::TokenName)
{
DPRINTF("Mesh file %s is invalid.\n", filename.c_str());
return NULL;
}
if (tokenizer.getStringValue() != "SphereDisplacementMesh")
{
DPRINTF("%s: Unrecognized mesh type %s.\n",
filename.c_str(),
tokenizer.getStringValue().c_str());
return NULL;
}
Value* meshDefValue = parser.readValue();
if (meshDefValue == NULL)
{
DPRINTF("%s: Bad mesh file.\n", filename.c_str());
return NULL;
}
if (meshDefValue->getType() != Value::HashType)
{
DPRINTF("%s: Bad mesh file.\n", filename.c_str());
delete meshDefValue;
return NULL;
}
Hash* meshDef = meshDefValue->getHash();
NoiseMeshParameters params;
params.size = Vec3f(1, 1, 1);
params.offset = Vec3f(10, 10, 10);
params.featureHeight = 0.0f;
params.octaves = 1;
params.slices = 20;
params.rings = 20;
meshDef->getVector("Size", params.size);
meshDef->getVector("NoiseOffset", params.offset);
meshDef->getNumber("FeatureHeight", params.featureHeight);
meshDef->getNumber("Octaves", params.octaves);
meshDef->getNumber("Slices", params.slices);
meshDef->getNumber("Rings", params.rings);
delete meshDefValue;
cout << "Read Celestia mesh " << filename << " successfully!";
return new SphereMesh(params.size,
(int) params.rings, (int) params.slices,
NoiseDisplacementFunc,
(void*) &params);
}

32
src/meshmanager.h 100644
View File

@ -0,0 +1,32 @@
// meshmanager.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _MESHMANAGER_H_
#define _MESHMANAGER_H_
#include <string>
#include <map>
#include "mesh.h"
#include "resmanager.h"
class MeshManager : public ResourceManager
{
public:
MeshManager() : ResourceManager() {};
MeshManager(string _baseDir) : ResourceManager(_baseDir) {};
MeshManager(char* _baseDir) : ResourceManager(_baseDir) {};
~MeshManager();
bool find(string name, Mesh**);
Mesh* load(string name);
};
#endif // _MESHMANAGER_H_

84
src/observer.cpp 100644
View File

@ -0,0 +1,84 @@
// observer.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "observer.h"
#define LY 9466411842000.000
Observer::Observer() : orientation(0, 0, 0, 1),
velocity(0, 0, 0)
{
}
UniversalCoord Observer::getPosition() const
{
return position;
}
Point3d Observer::getRelativePosition(Point3d& p) const
{
BigFix x(p.x);
BigFix y(p.y);
BigFix z(p.z);
double dx = (double) (position.x - x);
double dy = (double) (position.y - y);
double dz = (double) (position.z - z);
return Point3d(dx / LY, dy / LY, dz / LY);
}
Quatf Observer::getOrientation() const
{
return orientation;
}
void Observer::setOrientation(Quatf q)
{
orientation = q;
}
Vec3d Observer::getVelocity() const
{
return velocity;
}
void Observer::setVelocity(Vec3d v)
{
velocity = v;
}
void Observer::setPosition(Point3d p)
{
position = UniversalCoord(p);
}
void Observer::setPosition(UniversalCoord p)
{
position = p;
}
void Observer::update(double dt)
{
BigFix x(velocity.x * dt);
BigFix y(velocity.y * dt);
BigFix z(velocity.z * dt);
position.x = position.x + x;
position.y = position.y + y;
position.z = position.z + z;
}

58
src/observer.h 100644
View File

@ -0,0 +1,58 @@
// observer.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Because of the vastness of interstellar space, floats and doubles aren't
// sufficient when we need to represent distances to millimeter accuracy.
// BigFix is a high precision (128 bit) fixed point type used to represent
// the position of an observer in space. However, it's not practical to use
// high-precision numbers for the positions of everything. To get around
// this problem, object positions are stored at two different scales--light
// years for stars, and kilometers for objects within a star system.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include "bigfix.h"
#include "vecmath.h"
#include "univcoord.h"
#include "quaternion.h"
class Observer
{
public:
Observer();
// The getPosition method returns the observer's position in light
// years.
UniversalCoord getPosition() const;
// getRelativePosition returns in units of kilometers the difference
// between the position of the observer and a location specified in
// light years.
Point3d getRelativePosition(Point3d&) const;
Quatf getOrientation() const;
void setOrientation(Quatf);
Vec3d getVelocity() const;
void setVelocity(Vec3d);
void setPosition(BigFix x, BigFix y, BigFix z);
void setPosition(UniversalCoord);
void setPosition(Point3d);
void update(double dt);
private:
UniversalCoord position;
Quatf orientation;
Vec3d velocity;
};
#endif // _OBSERVER_H_

81
src/orbit.cpp 100644
View File

@ -0,0 +1,81 @@
// orbit.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include "mathlib.h"
#include "orbit.h"
EllipticalOrbit::EllipticalOrbit(double _semiMajorAxis,
double _eccentricity,
double _inclination,
double _ascendingNode,
double _argOfPeriapsis,
double _trueAnomaly,
double _period,
double _epoch) :
semiMajorAxis(_semiMajorAxis),
eccentricity(_eccentricity),
inclination(_inclination),
ascendingNode(_ascendingNode),
argOfPeriapsis(_argOfPeriapsis),
trueAnomaly(_trueAnomaly),
period(_period),
epoch(_epoch)
{
}
// First four terms of a series solution to Kepler's equation
// for orbital motion. This only works for small eccentricities,
// and in fact the series diverges for e > 0.6627434
static double solveKeplerSeries(double M, double e)
{
#if 0
return M + e * (sin(M) +
e * ((0.5 * sin(2 * M)) +
e * ((0.325 * sin(3 * M) - 0.125 * sin(M)) +
e * ((1.0 / 3.0 * sin(4 * M) - 1.0 / 6.0 * sin(2 * M))))));
#endif
return (M +
e * sin(M) +
e * e * 0.5 * sin(2 * M) +
e * e * e * (0.325 * sin(3 * M) - 0.125 * sin(M)) +
e * e * e * e * (1.0 / 3.0 * sin(4 * M) - 1.0 / 6.0 * sin(2 * M)));
}
// Return the offset from the barycenter
Point3d EllipticalOrbit::positionAtTime(double t) const
{
t = t - epoch;
double meanMotion = 2.0 * PI / period;
double meanAnomaly = trueAnomaly + t * meanMotion - argOfPeriapsis;
// TODO: calculate the *real* eccentric anomaly. This is a reasonable
// approximation only for nearly circular orbits
double eccAnomaly = meanAnomaly;
// eccAnomaly = solveKeplerSeries(meanAnomaly, eccentricity);
double x = semiMajorAxis * (cos(eccAnomaly) - eccentricity);
double z = semiMajorAxis * sqrt(1 - square(eccentricity)) * sin(eccAnomaly);
Mat3d R = (Mat3d::yrotation(ascendingNode) *
Mat3d::xrotation(inclination) *
Mat3d::yrotation(argOfPeriapsis));
return Point3d(x, 0, z) * R;
}
double EllipticalOrbit::getPeriod() const
{
return period;
}

45
src/orbit.h 100644
View File

@ -0,0 +1,45 @@
// orbit.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _ORBIT_H_
#define _ORBIT_H_
#include "vecmath.h"
class Orbit
{
public:
virtual Point3d positionAtTime(double) const = 0;
virtual double getPeriod() const = 0;
};
class EllipticalOrbit : public Orbit
{
public:
EllipticalOrbit(double, double, double, double, double, double, double,
double _epoch = 2451545.0);
// Compute the orbit for a specified Julian date
Point3d positionAtTime(double) const;
double getPeriod() const;
private:
double semiMajorAxis;
double eccentricity;
double inclination;
double ascendingNode;
double argOfPeriapsis;
double trueAnomaly;
double period;
double epoch;
};
#endif // _ORBIT_H_

446
src/packdb.cpp 100644
View File

@ -0,0 +1,446 @@
// packdb.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define SPECTRAL_O 0
#define SPECTRAL_B 1
#define SPECTRAL_A 2
#define SPECTRAL_F 3
#define SPECTRAL_G 4
#define SPECTRAL_K 5
#define SPECTRAL_M 6
#define SPECTRAL_R 7
#define SPECTRAL_S 8
#define SPECTRAL_N 9
#define SPECTRAL_WC 10
#define SPECTRAL_WN 11
// Stellar remnants
#define SPECTRAL_WHITE_DWARF 16
#define SPECTRAL_NEUTRON_STAR 32
#define SPECTRAL_UNKNOWN 255
#define LUM_Ia0 0
#define LUM_Ia 1
#define LUM_Ib 2
#define LUM_II 3
#define LUM_III 4
#define LUM_IV 5
#define LUM_V 6
#define LUM_VI 7
#define ID_NONE -1
#define HD_CATALOG 0x00000000
#define HIPPARCOS_CATALOG 0x10000000
#define BINWRITE(fp, n) fwrite(&(n), sizeof(n), 1, (fp))
typedef struct {
char colorType;
char subType;
char luminosity;
float colorIndex;
} SpectralType;
typedef struct {
int HIP; /* HIPPARCOS catalogue number */
int HD; /* HD catalogue number */
float appMag; /* Apparent magnitude */
float RA; /* 0 -- 24 hours */
float dec; /* -90 -- +90 degrees */
float parallax; /* in milliarcseconds */
char spectral[13];
unsigned char parallaxError;
} Star;
typedef struct {
int HD;
char *commonName;
char *altName;
} HDNameEnt;
/* Hardcoded file names */
#define HIPPARCOS_MAIN_DB "hip_main.dat"
#define COMMON_NAMES_DB "hdnames.dat"
HDNameEnt *hdNames;
int nHDNames;
Star *Stars;
int nStars;
int CompareHDNameEnt(const void *a, const void *b)
{
int hda = ((HDNameEnt *) a)->HD;
int hdb = ((HDNameEnt *) b)->HD;
if (hda < hdb)
return -1;
else if (hda > hdb)
return 1;
else
return 0;
}
unsigned short PackSpectralType(char *spectralType)
{
unsigned short packed = 0;
unsigned short letter;
unsigned short number;
unsigned short luminosity = LUM_V;
int i = 0;
// Subdwarves (luminosity class VI) are prefixed with sd
if (spectralType[i] == 's' && spectralType[i + 1] == 'd')
{
luminosity = LUM_VI;
i += 2;
}
switch (spectralType[i])
{
case 'O':
letter = SPECTRAL_O;
break;
case 'B':
letter = SPECTRAL_B;
break;
case 'A':
letter = SPECTRAL_A;
break;
case 'F':
letter = SPECTRAL_F;
break;
case 'G':
letter = SPECTRAL_G;
break;
case 'K':
letter = SPECTRAL_K;
break;
case 'M':
letter = SPECTRAL_M;
break;
case 'R':
letter = SPECTRAL_R;
break;
case 'N':
letter = SPECTRAL_N;
break;
case 'S':
letter = SPECTRAL_S;
break;
case 'W':
i++;
if (spectralType[i] == 'C')
letter = SPECTRAL_WC;
else if (spectralType[i] == 'N')
letter = SPECTRAL_WN;
else
i--;
break;
case 'D':
letter = SPECTRAL_WHITE_DWARF;
break;
default:
letter = SPECTRAL_UNKNOWN;
break;
}
if (letter == SPECTRAL_WHITE_DWARF)
return letter << 8;
i++;
if (spectralType[i] >= '0' && spectralType[i] <= '9')
number = spectralType[i] - '0';
else
number = 0;
if (luminosity != LUM_VI)
{
i++;
luminosity = LUM_V;
while (i < 13 && spectralType[i] != '\0') {
if (spectralType[i] == 'I') {
if (spectralType[i + 1] == 'I') {
if (spectralType[i + 2] == 'I') {
luminosity = LUM_III;
} else {
luminosity = LUM_II;
}
} else if (spectralType[i + 1] == 'V') {
luminosity = LUM_IV;
} else if (spectralType[i + 1] == 'a') {
if (spectralType[i + 2] == '0')
luminosity = LUM_Ia0;
else
luminosity = LUM_Ia;
} else if (spectralType[i + 1] == 'b') {
luminosity = LUM_Ib;
} else {
luminosity = LUM_Ib;
}
break;
} else if (spectralType[i] == 'V') {
if (spectralType[i + 1] == 'I')
luminosity = LUM_VI;
else
luminosity = LUM_V;
break;
}
i++;
}
}
return (letter << 8) | (number << 4) | luminosity;
}
HDNameEnt *ReadCommonNames(FILE *fp)
{
char buf[256];
int i;
hdNames = (HDNameEnt *) malloc(sizeof(HDNameEnt) * 3000);
if (hdNames == NULL)
return NULL;
for (i = 0; ; i++) {
char *name1, *name2, len;
if (fgets(buf, 256, fp) == NULL)
break;
/* Strip trailing newline */
len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
name1 = index(buf, ':');
if (name1 == NULL)
break;
name1[0] = '\0';
name1++;
name2 = index(name1, ':');
if (name2 == NULL)
break;
name2[0] = '\0';
name2++;
{
int hd;
if (sscanf(buf, "%d", &hd) != 1)
break;
hdNames[i].HD = hd;
if (name1[0] != '\0') {
hdNames[i].commonName = (char *) malloc(strlen(name1) + 1);
strcpy(hdNames[i].commonName, name1);
} else if (name2[0] != '\0') {
hdNames[i].commonName = (char *) malloc(strlen(name2) + 1);
strcpy(hdNames[i].commonName, name2);
}
}
}
nHDNames = i;
qsort(hdNames, nHDNames, sizeof(HDNameEnt), CompareHDNameEnt);
return hdNames;
}
char *LookupName(int HD)
{
HDNameEnt key;
HDNameEnt *found;
key.HD = HD;
found = (HDNameEnt *) bsearch((void *) &key, (void *) hdNames,
nHDNames, sizeof(HDNameEnt),
CompareHDNameEnt);
if (found == NULL)
return NULL;
else
return found->commonName;
}
void WriteStar(FILE *fp, Star *star)
{
unsigned short spectralType = PackSpectralType(star->spectral);
short appMag = (short) (star->appMag * 256);
unsigned int catalog_no;
if (star->HD != ID_NONE)
catalog_no = star->HD | HD_CATALOG;
else
catalog_no = star->HIP | HIPPARCOS_CATALOG;
BINWRITE(fp, catalog_no);
BINWRITE(fp, star->RA);
BINWRITE(fp, star->dec);
BINWRITE(fp, star->parallax);
BINWRITE(fp, appMag);
BINWRITE(fp, spectralType);
BINWRITE(fp, star->parallaxError);
}
#define HIPPARCOS_RECORD_LENGTH 512
Star *ReadHipparcosCatalog(FILE *fp)
{
char buf[HIPPARCOS_RECORD_LENGTH];
int i;
int maxStars = 120000;
Star *stars;
int nBright = 0, nGood = 0;
char nameBuf[20];
fprintf(stderr, "Attempting to allocate %d bytes\n", maxStars * sizeof(Star));
stars = (Star *) malloc(maxStars * sizeof(Star));
if (stars == NULL) {
fprintf(stderr, "Unable to allocate memory for stars.\n");
return NULL;
}
for (i = 0; ; i++) {
int hh, mm, deg;
float seconds;
float parallaxError;
char degSign;
if (fgets(buf, HIPPARCOS_RECORD_LENGTH, fp) == NULL)
break;
sscanf(buf + 2, "%d", &stars[i].HIP);
if (sscanf(buf + 390, "%d", &stars[i].HD) != 1)
stars[i].HD = ID_NONE;
sscanf(buf + 41, "%f", &stars[i].appMag);
sscanf(buf + 79, "%f", &stars[i].parallax);
sscanf(buf + 17, "%d %d %f", &hh, &mm, &seconds);
stars[i].RA = hh + (float) mm / 60.0f + (float) seconds / 3600.0f;
sscanf(buf + 29, "%c%d %d %f", &degSign, &deg, &mm, &seconds);
stars[i].dec = deg + (float) mm / 60.0f + (float) seconds / 3600.0f;
if (degSign == '-')
stars[i].dec = -stars[i].dec;
sscanf(buf + 435, "%12s", &stars[i].spectral);
sscanf(buf + 119, "%f", &parallaxError);
if (stars[i].parallax <= 0 || parallaxError / stars[i].parallax > 1)
{
stars[i].parallaxError = (unsigned char) 255;
}
else
{
stars[i].parallaxError =
(unsigned char) (parallaxError / stars[i].parallax * 200);
}
if (/* stars[i].appMag < 4.0f */
stars[i].parallax > 0 && 3260 / stars[i].parallax < 20) {
nBright++;
#if 0
if (parallaxError / stars[i].parallax > 0.25f ||
parallaxError / stars[i].parallax < 0.0f) {
#endif
if (0) {
char *name = LookupName(stars[i].HD);
if (name == NULL) {
if (stars[i].HD != ID_NONE) {
sprintf(nameBuf, "HD%d", stars[i].HD);
name = nameBuf;
} else {
sprintf(nameBuf, "HIP%d", stars[i].HIP);
name = nameBuf;
}
}
printf("%-20s %5.2f %6.2f %3d%% %12s %5.2f %5.2f\n",
name,
stars[i].appMag,
3260.0f / stars[i].parallax,
(int) (100.0f * parallaxError / stars[i].parallax),
stars[i].spectral,
stars[i].RA, stars[i].dec);
} else {
nGood++;
}
}
}
nStars = i;
printf("Stars: %d, Bright: %d, Good: %d\n", nStars, nBright, nGood);
return stars;
}
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(COMMON_NAMES_DB, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening %s\n", COMMON_NAMES_DB);
return 1;
}
hdNames = ReadCommonNames(fp);
fclose(fp);
fp = NULL;
if (hdNames == NULL) {
fprintf(stderr, "Error reading names file.\n");
return 1;
}
fp = fopen(HIPPARCOS_MAIN_DB, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening %s\n", HIPPARCOS_MAIN_DB);
return 1;
}
Stars = ReadHipparcosCatalog(fp);
fclose(fp);
if (Stars == NULL) {
fprintf(stderr, "Error reading HIPPARCOS database.");
return 1;
}
#if 0
{
int i;
for (i = 0; i < nStars; i++) {
if (Stars[i].spectral[0] == 'O') {
char *name = LookupName(Stars[i].HD);
if (name != NULL)
printf("%s ", name);
printf("%6d %6.3f %6.3f %s\n",
Stars[i].HD, Stars[i].RA, Stars[i].dec, Stars[i].spectral);
}
}
}
#endif
{
int i;
FILE *fp = fopen("out", "wb");
if (fp == NULL) {
fprintf(stderr, "Error opening output file.\n");
exit(1);
}
BINWRITE(fp, nStars);
for (i = 0; i < nStars; i++)
WriteStar(fp, &Stars[i]);
fclose(fp);
}
printf("Stars in catalog = %d\n", nStars);
}

125
src/packnames.cpp 100644
View File

@ -0,0 +1,125 @@
// packnames.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iostream>
#include <string>
#include "constellation.h"
#include "starname.h"
static char *greekAlphabet[] =
{
"Alpha",
"Beta",
"Gamma",
"Delta",
"Epsilon",
"Zeta",
"Eta",
"Theta",
"Iota",
"Kappa",
"Lambda",
"Mu",
"Nu",
"Xi",
"Omicron",
"Pi",
"Rho",
"Sigma",
"Tau",
"Upsilon",
"Phi",
"Chi",
"Psi",
"Omega"
};
int main(int argc, char *argv[])
{
string s;
for (;;)
{
unsigned int catalogNumber;
char sep;
cin >> catalogNumber;
if (cin.eof())
{
break;
}
else if (cin.bad())
{
cerr << "Error reading names file.\n";
break;
}
cin >> sep;
if (sep != ':')
{
cerr < "Missing ':' in names file.\n";
break;
}
// Get the rest of the line
getline(cin, s);
int nextSep = s.find_first_of(':');
if (nextSep == string::npos)
{
cerr << "Missing ':' in names file.\n";
break;
}
string common, designation;
string conAbbr;
string conName;
string bayerLetter;
if (nextSep != 0)
common = s.substr(0, nextSep);
designation = s.substr(nextSep + 1, string::npos);
if (designation != "")
{
nextSep = designation.find_last_of(' ');
if (nextSep != string::npos)
{
bayerLetter = designation.substr(0, nextSep);
conAbbr = designation.substr(nextSep + 1, string::npos);
}
}
Constellation *constel;
for (int i = 0; i < 88; i++)
{
constel = Constellation::getConstellation(i);
if (constel == NULL)
{
cerr << "Error getting constellation " << i << '\n';
break;
}
if (constel->getAbbreviation() == conAbbr)
{
conName = constel->getName();
break;
}
}
if (constel != NULL && bayerLetter != "")
{
StarName sn(common, bayerLetter, constel);
cout << sn.getDesignation() << ' ' << constel->getAbbreviation() << '\n';
}
}
}

524
src/parser.cpp 100644
View File

@ -0,0 +1,524 @@
// parser.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "parser.h"
/****** Value method implementations *******/
Value::Value(double d)
{
type = NumberType;
data.d = d;
}
Value::Value(string s)
{
type = StringType;
data.s = new string(s);
}
Value::Value(Array* a)
{
type = ArrayType;
data.a = a;
}
Value::Value(Hash* h)
{
type = HashType;
data.h = h;
}
Value::Value(bool b)
{
type = BooleanType;
data.d = b ? 1.0 : 0.0;
}
Value::~Value()
{
if (type == StringType)
{
delete data.s;
}
else if (type == ArrayType)
{
if (data.a != NULL)
{
for (int i = 0; i < data.a->size(); i++)
delete (*data.a)[i];
delete data.a;
}
}
else if (type == HashType)
{
if (data.h != NULL)
{
#if 0
Hash::iterator iter = data.h->begin();
while (iter != data.h->end())
{
delete iter->second;
iter++;
}
#endif
delete data.h;
}
}
}
Value::ValueType Value::getType() const
{
return type;
}
double Value::getNumber() const
{
// ASSERT(type == NumberType);
return data.d;
}
string Value::getString() const
{
// ASSERT(type == StringType);
return *data.s;
}
Array* Value::getArray() const
{
// ASSERT(type == ArrayType);
return data.a;
}
Hash* Value::getHash() const
{
// ASSERT(type == HashType);
return data.h;
}
bool Value::getBoolean() const
{
// ASSERT(type == BooleanType);
return (data.d != 0.0);
}
/****** Parser method implementation ******/
Parser::Parser(Tokenizer* _tokenizer) :
tokenizer(_tokenizer)
{
}
Array* Parser::readArray()
{
Tokenizer::TokenType tok = tokenizer->nextToken();
if (tok != Tokenizer::TokenBeginArray)
{
tokenizer->pushBack();
return NULL;
}
Array* array = new Array();
Value* v = readValue();
while (v != NULL)
{
array->insert(array->end(), v);
v = readValue();
}
tok = tokenizer->nextToken();
if (tok != Tokenizer::TokenEndArray)
{
tokenizer->pushBack();
delete array;
return NULL;
}
return array;
}
#if 0
Hash* Parser::readHash()
{
Tokenizer::TokenType tok = tokenizer->nextToken();
if (tok != Tokenizer::TokenBeginGroup)
{
tokenizer->pushBack();
return NULL;
}
Hash* hash = new Hash();
tok = tokenizer->nextToken();
while (tok != Tokenizer::TokenEndGroup)
{
if (tok != Tokenizer::TokenName)
{
tokenizer->pushBack();
delete hash;
return NULL;
}
string name = tokenizer->getNameValue();
Value* value = readValue();
if (value == NULL)
{
delete hash;
return NULL;
}
hash->insert(Hash::value_type(name, value));
tok = tokenizer->nextToken();
}
return hash;
}
#endif
Hash* Parser::readHash()
{
Tokenizer::TokenType tok = tokenizer->nextToken();
if (tok != Tokenizer::TokenBeginGroup)
{
tokenizer->pushBack();
return NULL;
}
Hash* hash = new Hash();
tok = tokenizer->nextToken();
while (tok != Tokenizer::TokenEndGroup)
{
if (tok != Tokenizer::TokenName)
{
tokenizer->pushBack();
delete hash;
return NULL;
}
string name = tokenizer->getNameValue();
Value* value = readValue();
if (value == NULL)
{
delete hash;
return NULL;
}
hash->addValue(name, *value);
tok = tokenizer->nextToken();
}
return hash;
}
Value* Parser::readValue()
{
Tokenizer::TokenType tok = tokenizer->nextToken();
switch (tok)
{
case Tokenizer::TokenNumber:
return new Value(tokenizer->getNumberValue());
case Tokenizer::TokenString:
return new Value(tokenizer->getStringValue());
case Tokenizer::TokenName:
if (tokenizer->getNameValue() == "false")
return new Value(false);
else if (tokenizer->getNameValue() == "true")
return new Value(true);
else
{
tokenizer->pushBack();
return NULL;
}
case Tokenizer::TokenBeginArray:
tokenizer->pushBack();
{
Array* array = readArray();
if (array == NULL)
return NULL;
else
return new Value(array);
}
case Tokenizer::TokenBeginGroup:
tokenizer->pushBack();
{
Hash* hash = readHash();
if (hash == NULL)
return NULL;
else
return new Value(hash);
}
default:
tokenizer->pushBack();
return NULL;
}
}
#if 0
// TODO: Move all these get* functions into a Hash class.
bool getNumber(Hash* h, string name, double& val)
{
Hash::iterator iter = h->find(name);
if (iter == h->end())
return false;
Value* v = iter->second;
if (v->getType() != Value::NumberType)
return false;
val = v->getNumber();
return true;
}
bool getNumber(Hash* h, string name, float& val)
{
double dval;
if (!getNumber(h, name, dval))
{
return false;
}
else
{
val = (float) dval;
return true;
}
}
bool getString(Hash* h, string name, string& val)
{
Hash::iterator iter = h->find(name);
if (iter == h->end())
return false;
Value* v = iter->second;
if (v->getType() != Value::StringType)
return false;
val = v->getString();
return true;
}
bool getBoolean(Hash* h, string name, bool& val)
{
Hash::iterator iter = h->find(name);
if (iter == h->end())
return false;
Value* v = iter->second;
if (v->getType() != Value::BooleanType)
return false;
val = v->getBoolean();
return true;
}
bool getVector(Hash* h, string name, Vec3d& val)
{
Hash::iterator iter = h->find(name);
if (iter == h->end())
return false;
Value* v = iter->second;
if (v->getType() != Value::ArrayType)
return false;
Array* arr = v->getArray();
if (arr->size() != 3)
return false;
Value* x = (*arr)[0];
Value* y = (*arr)[1];
Value* z = (*arr)[2];
if (x->getType() != Value::NumberType ||
y->getType() != Value::NumberType ||
z->getType() != Value::NumberType)
return false;
val = Vec3d((float) x->getNumber(),
(float) y->getNumber(),
(float) z->getNumber());
return true;
}
bool getVector(Hash* h, string name, Vec3f& val)
{
Vec3d vecVal;
if (!getVector(h, name, vecVal))
return false;
val = Vec3f((float) vecVal.x, (float) vecVal.y, (float) vecVal.z);
return true;
}
bool getColor(Hash* h, string name, Color& val)
{
Vec3d vecVal;
if (!getVector(h, name, vecVal))
return false;
val = Color((float) vecVal.x, (float) vecVal.y, (float) vecVal.z);
return true;
}
#endif
AssociativeArray::AssociativeArray()
{
}
AssociativeArray::~AssociativeArray()
{
#if 0
Hash::iterator iter = data.h->begin();
while (iter != data.h->end())
{
delete iter->second;
iter++;
}
#endif
for (map<string, Value*>::iterator iter = assoc.begin(); iter != assoc.end(); iter++)
delete iter->second;
}
Value* AssociativeArray::getValue(string key) const
{
map<string, Value*>::const_iterator iter = assoc.find(key);
if (iter == assoc.end())
return NULL;
else
return iter->second;
}
void AssociativeArray::addValue(string key, Value& val)
{
assoc.insert(map<string, Value*>::value_type(key, &val));
}
bool AssociativeArray::getNumber(string key, double& val) const
{
Value* v = getValue(key);
if (v == NULL || v->getType() != Value::NumberType)
return false;
val = v->getNumber();
return true;
}
bool AssociativeArray::getNumber(string key, float& val) const
{
double dval;
if (!getNumber(key, dval))
{
return false;
}
else
{
val = (float) dval;
return true;
}
}
bool AssociativeArray::getString(string key, string& val) const
{
Value* v = getValue(key);
if (v == NULL || v->getType() != Value::StringType)
return false;
val = v->getString();
return true;
}
bool AssociativeArray::getBoolean(string key, bool& val) const
{
Value* v = getValue(key);
if (v == NULL || v->getType() != Value::BooleanType)
return false;
val = v->getBoolean();
return true;
}
bool AssociativeArray::getVector(string key, Vec3d& val) const
{
Value* v = getValue(key);
if (v == NULL || v->getType() != Value::ArrayType)
return false;
Array* arr = v->getArray();
if (arr->size() != 3)
return false;
Value* x = (*arr)[0];
Value* y = (*arr)[1];
Value* z = (*arr)[2];
if (x->getType() != Value::NumberType ||
y->getType() != Value::NumberType ||
z->getType() != Value::NumberType)
return false;
val = Vec3d((float) x->getNumber(),
(float) y->getNumber(),
(float) z->getNumber());
return true;
}
bool AssociativeArray::getVector(string key, Vec3f& val) const
{
Vec3d vecVal;
if (!getVector(key, vecVal))
return false;
val = Vec3f((float) vecVal.x, (float) vecVal.y, (float) vecVal.z);
return true;
}
bool AssociativeArray::getColor(string key, Color& val) const
{
Vec3d vecVal;
if (!getVector(key, vecVal))
return false;
val = Color((float) vecVal.x, (float) vecVal.y, (float) vecVal.z);
return true;
}

96
src/parser.h 100644
View File

@ -0,0 +1,96 @@
// parser.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _PARSER_H_
#define _PARSER_H_
#include <vector>
#include <map>
#include "vecmath.h"
#include "color.h"
#include "tokenizer.h"
class Value;
class AssociativeArray
{
public:
AssociativeArray();
~AssociativeArray();
Value* getValue(string) const;
void addValue(string, Value&);
bool getNumber(string, double&) const;
bool getNumber(string, float&) const;
bool getString(string, string&) const;
bool getBoolean(string, bool&) const;
bool getVector(string, Vec3d&) const;
bool getVector(string, Vec3f&) const;
bool getColor(string, Color&) const;
private:
map<string, Value*> assoc;
};
typedef vector<Value*> Array;
typedef AssociativeArray Hash;
class Value
{
public:
enum ValueType {
NumberType = 0,
StringType = 1,
ArrayType = 2,
HashType = 3,
BooleanType = 4
};
Value(double);
Value(string);
Value(Array*);
Value(Hash*);
Value(bool);
~Value();
ValueType getType() const;
double getNumber() const;
string getString() const;
Array* getArray() const;
Hash* getHash() const;
bool getBoolean() const;
private:
ValueType type;
union {
string* s;
double d;
Array* a;
Hash* h;
} data;
};
class Parser
{
public:
Parser(Tokenizer*);
Array* readArray();
Hash* readHash();
Value* readValue();
private:
Tokenizer* tokenizer;
};
#endif // _PARSER_H_

333
src/perlin.cpp 100644
View File

@ -0,0 +1,333 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mathlib.h"
#include "vecmath.h"
#include "perlin.h"
float bias(float a, float b)
{
return (float) pow(a, log(b) / log(0.5));
}
float gain(float a, float b)
{
float p = (float) (log(1.0 - b) / log(0.5));
if (a < 0.001f)
return 0.0f;
else if (a > 0.999f)
return 1.0f;
if (a < 0.5f)
return (float) pow(2 * a, p) / 2;
else
return 1.0f - (float) pow(2 * (1.0 - a), p) / 2;
}
float noise(float vec[], int len)
{
switch (len) {
case 0:
return 0.;
case 1:
return noise1(vec[0]);
case 2:
return noise2(vec);
default:
return noise3(vec);
}
}
float turbulence(float v[], float freq)
{
float t, vec[3];
for (t = 0. ; freq >= 1. ; freq /= 2) {
vec[0] = freq * v[0];
vec[1] = freq * v[1];
vec[2] = freq * v[2];
t += (float) fabs(noise3(vec)) / freq;
}
return t;
}
float turbulence(Point2f& p, float freq)
{
float t;
float vec[2];
for (t = 0.0f; freq >= 1.0f; freq *= 0.5f)
{
vec[0] = freq * p.x;
vec[1] = freq * p.y;
t += (float) fabs(noise2(vec)) / freq;
}
return t;
}
float turbulence(Point3f& p, float freq)
{
float t;
float vec[3];
for (t = 0.0f; freq >= 1.0f; freq *= 0.5f)
{
vec[0] = freq * p.x;
vec[1] = freq * p.y;
vec[2] = freq * p.z;
t += (float) fabs(noise3(vec)) / freq;
}
return t;
}
float fractalsum(float v[], float freq)
{
float t;
float vec[3];
for (t = 0.0f ; freq >= 1.0f ; freq /= 2.0f) {
vec[0] = freq * v[0];
vec[1] = freq * v[1];
vec[2] = freq * v[2];
t += noise3(vec) / freq;
}
return t;
}
float fractalsum(Point2f& p, float freq)
{
float t;
float vec[2];
for (t = 0.0f; freq >= 1.0f; freq *= 0.5f)
{
vec[0] = freq * p.x;
vec[1] = freq * p.y;
t += noise2(vec) / freq;
}
return t;
}
float fractalsum(Point3f& p, float freq)
{
float t;
float vec[3];
for (t = 0.0f; freq >= 1.0f; freq *= 0.5f)
{
vec[0] = freq * p.x;
vec[1] = freq * p.y;
vec[2] = freq * p.z;
t += noise3(vec) / freq;
}
return t;
}
/* noise functions over 1, 2, and 3 dimensions */
#define B 0x100
#define BM 0xff
#define N 0x1000
#define NP 12 /* 2^N */
#define NM 0xfff
static int p[B + B + 2];
static float g3[B + B + 2][3];
static float g2[B + B + 2][2];
static float g1[B + B + 2];
static bool initialized = false;
static void init(void);
#define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
#define setup(i, b0, b1, r0, r1) \
t = vec[i] + N;\
b0 = ((int)t) & BM;\
b1 = (b0+1) & BM;\
r0 = t - (int)t;\
r1 = r0 - 1.0f;
float noise1(float arg)
{
if (!initialized)
init();
int bx0, bx1;
float rx0, rx1, t, u, v, vec[1];
vec[0] = arg;
setup(0, bx0, bx1, rx0, rx1);
u = rx0 * g1[p[bx0]];
v = rx1 * g1[p[bx1]];
return Mathf::lerp(s_curve(rx0), u, v);
}
float noise2(float vec[2])
{
int bx0, bx1, by0, by1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
int i, j;
if (!initialized)
init();
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
i = p[ bx0 ];
j = p[ bx1 ];
b00 = p[ i + by0 ];
b10 = p[ j + by0 ];
b01 = p[ i + by1 ];
b11 = p[ j + by1 ];
sx = s_curve(rx0);
sy = s_curve(ry0);
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
q = g2[ b00 ] ; u = at2(rx0,ry0);
q = g2[ b10 ] ; v = at2(rx1,ry0);
a = Mathf::lerp(sx, u, v);
q = g2[ b01 ] ; u = at2(rx0,ry1);
q = g2[ b11 ] ; v = at2(rx1,ry1);
b = Mathf::lerp(sx, u, v);
return Mathf::lerp(sy, a, b);
}
float noise3(float vec[3])
{
if (!initialized)
init();
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
int i, j;
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
setup(2, bz0,bz1, rz0,rz1);
i = p[ bx0 ];
j = p[ bx1 ];
b00 = p[ i + by0 ];
b10 = p[ j + by0 ];
b01 = p[ i + by1 ];
b11 = p[ j + by1 ];
t = s_curve(rx0);
sy = s_curve(ry0);
sz = s_curve(rz0);
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
a = Mathf::lerp(t, u, v);
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
b = Mathf::lerp(t, u, v);
c = Mathf::lerp(sy, a, b);
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
a = Mathf::lerp(t, u, v);
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
b = Mathf::lerp(t, u, v);
d = Mathf::lerp(sy, a, b);
return Mathf::lerp(sz, c, d);
}
static void normalize2(float v[2])
{
float s = (float) sqrt(v[0] * v[0] + v[1] * v[1]);
v[0] = v[0] / s;
v[1] = v[1] / s;
}
static void normalize3(float v[3])
{
float s = (float) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] = v[0] / s;
v[1] = v[1] / s;
v[2] = v[2] / s;
}
static void init()
{
int i, j, k;
for (i = 0; i < B; i++)
{
g1[i] = Mathf::sfrand();
g2[i][0] = Mathf::sfrand();
g2[i][1] = Mathf::sfrand();
normalize2(g2[i]);
g3[i][0] = Mathf::sfrand();
g3[i][1] = Mathf::sfrand();
g3[i][2] = Mathf::sfrand();
normalize3(g3[i]);
}
// Fill the permutation array with values . . .
for (i = 0; i < B; i++)
p[i] = i;
// . . . and then shuffle it
for (i = 0; i < B; i++)
{
k = p[i];
j = rand() % B;
p[i] = p[j];
p[j] = k;
}
// Duplicate values to accelerate table lookups
for (i = 0; i < B + 2; i++)
{
p[B + i] = p[i];
g1[B + i] = g1[i];
g2[B + i][0] = g2[i][0];
g2[B + i][1] = g2[i][1];
g3[B + i][0] = g3[i][0];
g3[B + i][1] = g3[i][1];
g3[B + i][2] = g3[i][2];
}
initialized = true;
}

19
src/perlin.h 100644
View File

@ -0,0 +1,19 @@
// perlin.h
#ifndef _PERLIN_H_
#define _PERLIN_H_
extern float noise(float vec[], int len);
extern float noise1(float arg);
extern float noise2(float vec[]);
extern float noise3(float vec[]);
extern float turbulence(float v[], float freq);
extern float turbulence(Point2f& p, float freq);
extern float turbulence(Point3f& p, float freq);
extern float fractalsum(float v[], float freq);
extern float fractalsum(Point2f& p, float freq);
extern float fractalsum(Point3f& p, float freq);
#endif // _PERLIN_H_

595
src/quaternion.h 100644
View File

@ -0,0 +1,595 @@
// quaternion.h
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// Template-ized quaternion math library.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _QUATERNION_H_
#define _QUATERNION_H_
#include "mathlib.h"
#include "vecmath.h"
template<class T> class Quaternion
{
public:
inline Quaternion();
inline Quaternion(const Quaternion<T>&);
inline Quaternion(T);
inline Quaternion(const Vector3<T>&);
inline Quaternion(T, const Vector3<T>&);
inline Quaternion(T, T, T, T);
Quaternion(Matrix3<T>&);
inline Quaternion& operator+=(Quaternion);
inline Quaternion& operator-=(Quaternion);
inline Quaternion& operator*=(T);
Quaternion& operator*=(Quaternion);
inline Quaternion operator~(); // conjugate
inline Quaternion operator-();
inline Quaternion operator+();
void setAxisAngle(Vector3<T> axis, T angle);
void getAxisAngle(Vector3<T>& axis, T& angle) const;
Matrix4<T> toMatrix4() const;
Matrix3<T> toMatrix3() const;
static Quaternion<T> slerp(Quaternion<T>, Quaternion<T>, T);
void rotate(Vector3<T> axis, T angle);
void xrotate(T angle);
void yrotate(T angle);
void zrotate(T angle);
bool isPure() const;
bool isReal() const;
T normalize();
friend Quaternion operator+(Quaternion, Quaternion);
friend Quaternion operator-(Quaternion, Quaternion);
friend Quaternion operator*(Quaternion, Quaternion);
friend Quaternion operator*(T, Quaternion);
friend Quaternion operator*(Vector3<T>, Quaternion);
friend bool operator==(Quaternion, Quaternion);
friend bool operator!=(Quaternion, Quaternion);
friend T real(Quaternion);
friend Vector3<T> imag(Quaternion);
// private:
T w, x, y, z;
};
typedef Quaternion<float> Quatf;
typedef Quaternion<double> Quatd;
template<class T> Quaternion<T>::Quaternion() : w(0), x(0), y(0), z(0)
{
}
template<class T> Quaternion<T>::Quaternion(const Quaternion<T>& q) :
w(q.w), x(q.x), y(q.y), z(q.z)
{
}
template<class T> Quaternion<T>::Quaternion(T re) :
w(re), x(0), y(0), z(0)
{
}
// Create a 'pure' quaternion
template<class T> Quaternion<T>::Quaternion(const Vector3<T>& im) :
w(0), x(im.x), y(im.y), z(im.z)
{
}
template<class T> Quaternion<T>::Quaternion(T re, const Vector3<T>& im) :
w(re), x(im.x), y(im.y), z(im.z)
{
}
template<class T> Quaternion<T>::Quaternion(T _w, T _x, T _y, T _z) :
w(_w), x(_x), y(_y), z(_z)
{
}
// Create a quaternion from a rotation matrix
template<class T> Quaternion<T>::Quaternion(Matrix3<T>& m)
{
T trace = m[0][0] + m[1][1] + m[2][2];
T root;
if (trace > 0)
{
root = (T) sqrt(trace + 1);
w = (T) 0.5 * root;
root = (T) 0.5 / root;
x = (m[2][1] - m[1][2]) * root;
y = (m[0][2] - m[2][0]) * root;
z = (m[1][0] - m[0][1]) * root;
}
else
{
int i = 0;
if (m[1][1] > m[1][1])
i = 1;
if (m[2][2] > m[1][1])
i = 2;
int j = (i == 2) ? 0 : i + 1;
int k = (j == 2) ? 0 : j + 1;
root = (T) sqrt(m[i][i] - m[j][j] - m[k][k] + 1);
T* xyz[3] = { &x, &y, &z };
*xyz[i] = (T) 0.5 * root;
root = (T) 0.5 / root;
w = (m[k][j] - m[j][k]) * root;
*xyz[j] = (m[j][i] + m[i][j]) * root;
*xyz[k] = (m[k][i] + m[i][k]) * root;
}
}
template<class T> Quaternion<T>& Quaternion<T>::operator+=(Quaternion<T> a)
{
x += a.x; y += a.y; z += a.z; w += a.w;
return *this;
}
template<class T> Quaternion<T>& Quaternion<T>::operator-=(Quaternion<T> a)
{
x -= a.x; y -= a.y; z -= a.z; w -= a.w;
return *this;
}
template<class T> Quaternion<T>& Quaternion<T>::operator*=(Quaternion<T> q)
{
*this = Quaternion<T>(w * q.w - x * q.x - y * q.y - z * q.z,
w * q.x + x * q.w + y * q.z - z * q.y,
w * q.y + y * q.w + z * q.x - x * q.z,
w * q.z + z * q.w + x * q.y - y * q.x);
return *this;
}
template<class T> Quaternion<T>& Quaternion<T>::operator*=(T s)
{
x *= s; y *= s; z *= s; w *= s;
return *this;
}
// conjugate operator
template<class T> Quaternion<T> Quaternion<T>::operator~()
{
return Quaternion<T>(w, -x, -y, -z);
}
template<class T> Quaternion<T> Quaternion<T>::operator-()
{
return Quaternion<T>(-w, -x, -y, -z);
}
template<class T> Quaternion<T> Quaternion<T>::operator+()
{
return *this;
}
template<class T> Quaternion<T> operator+(Quaternion<T> a, Quaternion<T> b)
{
return Quaternion<T>(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z);
}
template<class T> Quaternion<T> operator-(Quaternion<T> a, Quaternion<T> b)
{
return Quaternion<T>(a.w - b.w, a.x - b.x, a.y - b.y, a.z - b.z);
}
template<class T> Quaternion<T> operator*(Quaternion<T> a, Quaternion<T> b)
{
return Quaternion<T>(a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z,
a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x);
}
template<class T> Quaternion<T> operator*(T s, Quaternion<T> q)
{
return Quaternion<T>(s * q.w, s * q.x, s * q.y, s * q.z);
}
template<class T> Quaternion<T> operator*(Quaternion<T> q, T s)
{
return Quaternion<T>(s * q.w, s * q.x, s * q.y, s * q.z);
}
// equivalent to multiplying by the quaternion (0, v)
template<class T> Quaternion<T> operator*(Vector3<T> v, Quaternion<T> q)
{
return Quaternion<T>(-v.x * q.x - v.y * q.y - v.z * q.z,
v.x * q.w + v.y * q.z - v.z * q.y,
v.y * q.w + v.z * q.x - v.x * q.z,
v.z * q.w + v.x * q.y - v.y * q.x);
}
template<class T> Quaternion<T> operator/(Quaternion<T> q, T s)
{
return q * (1 / s);
}
template<class T> Quaternion<T> operator/(Quaternion<T> a, Quaternion<T> b)
{
return a * (~b / abs(b));
}
template<class T> bool operator==(Quaternion<T> a, Quaternion<T> b)
{
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}
template<class T> bool operator!=(Quaternion<T> a, Quaternion<T> b)
{
return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
}
// elementary functions
template<class T> Quaternion<T> conjugate(Quaternion<T> q)
{
return Quaternion<T>(q.w, -q.x, -q.y, -q.z);
}
template<class T> T norm(Quaternion<T> q)
{
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
}
template<class T> T abs(Quaternion<T> q)
{
return (T) sqrt(norm(q));
}
template<class T> Quaternion<T> exp(Quaternion<T> q)
{
if (q.isReal())
{
return Quaternion<T>((T) exp(q.w));
}
else
{
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
T s = (T) sin(l);
T c = (T) cos(l);
T e = (T) exp(q.w);
T t = e * s / l;
return Quaternion<T>(e * c, t * q.x, t * q.y, t * q.z);
}
}
template<class T> Quaternion<T> log(Quaternion<T> q)
{
if (q.isReal())
{
if (q.w > 0)
{
return Quaternion<T>((T) log(q.w));
}
else if (q.w < 0)
{
// The log of a negative purely real quaternion has
// infinitely many values, all of the form (ln(-w), PI * I),
// where I is any unit vector. We arbitrarily choose an I
// of (1, 0, 0) here and whereever else a similar choice is
// necessary. Geometrically, the set of roots is a sphere
// of radius PI centered at ln(-w) on the real axis.
return Quaternion<T>((T) log(-q.w), (T) PI, 0, 0);
}
else
{
// error . . . ln(0) not defined
return Quaternion<T>(0);
}
}
else
{
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
T r = (T) sqrt(l * l + q.w * q.w);
T theta = (T) atan2(l, q.w);
T t = theta / l;
return Quaternion<T>((T) log(r), t * q.x, t * q.y, t * q.z);
}
}
template<class T> Quaternion<T> pow(Quaternion<T> q, T s)
{
return exp(s * log(q));
}
template<class T> Quaternion<T> pow(Quaternion<T> q, Quaternion<T> p)
{
return exp(p * log(q));
}
template<class T> Quaternion<T> sin(Quaternion<T> q)
{
if (q.isReal())
{
return Quaternion<T>((T) sin(q.w));
}
else
{
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
T m = q.w;
T s = (T) sin(m);
T c = (T) cos(m);
T il = 1 / l;
T e0 = (T) exp(-l);
T e1 = (T) exp(l);
T c0 = (T) -0.5 * e0 * il * c;
T c1 = (T) 0.5 * e1 * il * c;
return Quaternion<T>((T) 0.5 * e0 * s, c0 * q.x, c0 * q.y, c0 * q.z) +
Quaternion<T>((T) 0.5 * e1 * s, c1 * q.x, c1 * q.y, c1 * q.z);
}
}
template<class T> Quaternion<T> cos(Quaternion<T> q)
{
if (q.isReal())
{
return Quaternion<T>((T) cos(q.w));
}
else
{
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
T m = q.w;
T s = (T) sin(m);
T c = (T) cos(m);
T il = 1 / l;
T e0 = (T) exp(-l);
T e1 = (T) exp(l);
T c0 = (T) 0.5 * e0 * il * s;
T c1 = (T) -0.5 * e1 * il * s;
return Quaternion<T>((T) 0.5 * e0 * c, c0 * q.x, c0 * q.y, c0 * q.z) +
Quaternion<T>((T) 0.5 * e1 * c, c1 * q.x, c1 * q.y, c1 * q.z);
}
}
template<class T> Quaternion<T> sqrt(Quaternion<T> q)
{
// In general, the square root of a quaternion has two values, one
// of which is the negative of the other. However, any negative purely
// real quaternion has an infinite number of square roots.
// This function returns the positive root for positive reals and
// the root on the positive i axis for negative reals.
if (q.isReal())
{
if (q.w >= 0)
return Quaternion<T>((T) sqrt(q.w), 0, 0, 0);
else
return Quaternion<T>(0, (T) sqrt(-q.w), 0, 0);
}
else
{
T b = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
T r = (T) sqrt(q.w * q.w + b * b);
if (q.w >= 0)
{
T m = (T) sqrt((T) 0.5 * (r + q.w));
T l = b / (2 * m);
T t = l / b;
return Quaternion<T>(m, q.x * t, q.y * t, q.z * t);
}
else
{
T l = (T) sqrt((T) 0.5 * (r - q.w));
T m = b / (2 * l);
T t = l / b;
return Quaternion<T>(m, q.x * t, q.y * t, q.z * t);
}
}
}
template<class T> T real(Quaternion<T> q)
{
return q.w;
}
template<class T> Vector3<T> imag(Quaternion<T> q)
{
return Vector3<T>(q.x, q.y, q.z);
}
// Quaternion methods
template<class T> bool Quaternion<T>::isReal() const
{
return (x == 0 && y == 0 && z == 0);
}
template<class T> bool Quaternion<T>::isPure() const
{
return w == 0;
}
template<class T> T Quaternion<T>::normalize()
{
T s = abs(*this);
T invs = (T) 1 / (T) s;
x *= invs;
y *= invs;
z *= invs;
w *= invs;
return s;
}
// Set to the unit quaternion representing an axis angle rotation. Assume
// that axis is a unit vector
template<class T> void Quaternion<T>::setAxisAngle(Vector3<T> axis, T angle)
{
T s, c;
Math<T>::sincos(angle * (T) 0.5, s, c);
x = s * axis.x;
y = s * axis.y;
z = s * axis.z;
w = c;
}
// Assuming that this a unit quaternion, return the in axis/angle form the
// orientation which it represents.
template<class T> void Quaternion<T>::getAxisAngle(Vector3<T>& axis,
T& angle) const
{
// The quaternion has the form:
// w = cos(angle/2), (x y z) = sin(angle/2)*axis
T magSquared = x * x + y * y + z * z;
if (magSquared > (T) 1e-10)
{
T s = (T) 1 / (T) sqrt(magSquared);
axis.x = x * s;
axis.y = y * s;
axis.z = z * s;
if (w <= -1 || w >= 1)
angle = 0;
else
angle = (T) acos(w) * 2;
}
else
{
// The angle is zero, so we pick an arbitrary unit axis
axis.x = 1;
axis.y = 0;
axis.z = 0;
angle = 0;
}
}
// Convert this (assumed to be normalized) quaternion to a rotation matrix
template<class T> Matrix4<T> Quaternion<T>::toMatrix4() const
{
T wx = w * x * 2;
T wy = w * y * 2;
T wz = w * z * 2;
T xx = x * x * 2;
T xy = x * y * 2;
T xz = x * z * 2;
T yy = y * y * 2;
T yz = y * z * 2;
T zz = z * z * 2;
return Matrix4<T>(Vector4<T>(1 - yy - zz, xy + wz, xz - wy, 0),
Vector4<T>(xy - wz, 1 - xx - zz, yz + wx, 0),
Vector4<T>(xz + wy, yz - wx, 1 - xx - yy, 0),
Vector4<T>(0, 0, 0, 1));
}
// Convert this (assumed to be normalized) quaternion to a rotation matrix
template<class T> Matrix3<T> Quaternion<T>::toMatrix3() const
{
T wx = w * x * 2;
T wy = w * y * 2;
T wz = w * z * 2;
T xx = x * x * 2;
T xy = x * y * 2;
T xz = x * z * 2;
T yy = y * y * 2;
T yz = y * z * 2;
T zz = z * z * 2;
return Matrix3<T>(Vector3<T>(1 - yy - zz, xy + wz, xz - wy),
Vector3<T>(xy - wz, 1 - xx - zz, yz + wx),
Vector3<T>(xz + wy, yz - wx, 1 - xx - yy));
}
template<class T> T dot(Quaternion<T> a, Quaternion<T> b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
template<class T> Quaternion<T> Quaternion<T>::slerp(Quaternion<T> q0,
Quaternion<T> q1,
T t)
{
T c = dot(q0, q1);
T angle = (T) acos(c);
if (abs(angle) < (T) 1.0e-5)
return q0;
T s = (T) sin(angle);
T is = (T) 1.0 / s;
return q0 * ((T) sin((1 - t) * angle) * is) +
q1 * ((T) sin(t * angle) * is);
}
// Assuming that this is a unit quaternion representing an orientation,
// apply a rotation of angle radians about the specfied axis
template<class T> void Quaternion<T>::rotate(Vector3<T> axis, T angle)
{
Quaternion q;
q.setAxisAngle(axis, angle);
*this = q * *this;
}
// Assuming that this is a unit quaternion representing an orientation,
// apply a rotation of angle radians about the x-axis
template<class T> void Quaternion<T>::xrotate(T angle)
{
T s, c;
Math<T>::sincos(angle * (T) 0.5, s, c);
*this = Quaternion<T>(c, s, 0, 0) * *this;
}
// Assuming that this is a unit quaternion representing an orientation,
// apply a rotation of angle radians about the y-axis
template<class T> void Quaternion<T>::yrotate(T angle)
{
T s, c;
Math<T>::sincos(angle * (T) 0.5, s, c);
*this = Quaternion<T>(c, 0, s, 0) * *this;
}
// Assuming that this is a unit quaternion representing an orientation,
// apply a rotation of angle radians about the z-axis
template<class T> void Quaternion<T>::zrotate(T angle)
{
T s, c;
Math<T>::sincos(angle * (T) 0.5, s, c);
*this = Quaternion<T>(c, 0, 0, s) * *this;
}
#endif // _QUATERNION_H_

81
src/readstars.cpp 100644
View File

@ -0,0 +1,81 @@
// readstars.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include <iostream>
#define MAX_STARS 120000
#define PI 3.1415926535898
#include "basictypes.h"
#include "stellarclass.h"
#include "star.h"
int main(int argc, char *argv[])
{
Star *stars = new Star[MAX_STARS];
int nStars = 0;
float brightest = 100000;
while (nStars < MAX_STARS) {
uint32 catNo = 0;
float RA = 0, dec = 0, parallax = 0;
int16 appMag;
uint16 stellarClass;
cin.read((void *) &catNo, sizeof catNo);
cin.read((void *) &RA, sizeof RA);
cin.read((void *) &dec, sizeof dec);
cin.read((void *) &parallax, sizeof parallax);
cin.read((void *) &appMag, sizeof appMag);
cin.read((void *) &stellarClass, sizeof stellarClass);
if (!cin.good())
break;
Star *star = &stars[nStars];
// Compute distance based on parallax
double distance = 3.26 / (parallax > 0.0 ? parallax / 1000.0 : 1e-6);
// Convert from RA, dec spherical to cartesian coordinates
double theta = RA / 24.0 * PI * 2;
double phi = (1.0 - dec / 90.0) * PI / 2;
double x = cos(theta) * sin(phi) * distance;
double y = cos(phi) * distance;
double z = sin(theta) * sin(phi) * distance;
star->setPosition((float) x, (float) y, (float) z);
// Use apparent magnitude and distance to determine the absolute
// magnitude of the star.
star->setAbsoluteMagnitude((float) (appMag / 256.0 + 5 -
5 * log10(distance / 3.26)));
StellarClass sc((StellarClass::StarType) (stellarClass >> 12),
(StellarClass::SpectralClass)(stellarClass >> 8 & 0xf),
(unsigned int) (stellarClass >> 4 & 0xf),
(StellarClass::LuminosityClass) (stellarClass & 0xf));
star->setStellarClass(sc);
star->setCatalogNumber(catNo);
if (parallax > 0.0 && star->getAbsoluteMagnitude() < brightest)
{
brightest = star->getAbsoluteMagnitude();
cout << brightest << ' ' << sc << '\n';
}
nStars++;
}
cout << nStars << '\n';
cout << sizeof(StellarClass) << '\n';
cout << sizeof(stars[0]) << '\n';
}

1385
src/render.cpp 100644

File diff suppressed because it is too large Load Diff

201
src/render.h 100644
View File

@ -0,0 +1,201 @@
// render.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _RENDER_H_
#define _RENDER_H_
#include <vector>
#include <string>
#include "stardb.h"
#include "visstars.h"
#include "observer.h"
#include "solarsys.h"
#include "texmanager.h"
#include "meshmanager.h"
#include "console.h"
#include "selection.h"
class Renderer
{
public:
Renderer();
~Renderer();
bool init(int, int);
void shutdown() {};
void resize(int, int);
float getFieldOfView();
void setFieldOfView(float);
void setRenderMode(int);
void render(const Observer&,
const StarDatabase&,
const VisibleStarSet&,
SolarSystem*,
const Selection& sel,
double now);
// Convert window coordinates to a ray for picking
Vec3f getPickRay(int winX, int winY);
Console* getConsole();
enum {
NoLabels = 0,
StarLabels = 1,
PlanetLabels = 2,
PlanetOrbits = 4
};
int getLabelMode() const;
void setLabelMode(int);
void addLabelledStar(Star*);
void clearLabelledStars();
float getAmbientLightLevel() const;
void setAmbientLightLevel(float);
typedef struct {
string text;
Color color;
Point3f position;
} Label;
void addLabel(string, Color, Point3f);
void clearLabels();
public:
// Internal types
// TODO: Figure out how to make these private. Even with a friend
//
struct Particle
{
Point3f center;
float size;
Color color;
float pad0, pad1, pad2;
};
typedef struct _RenderListEntry
{
Star* star;
Body* body;
Point3f position;
Vec3f sun;
float distance;
float discSizeInPixels;
float appMag;
bool operator<(const _RenderListEntry& r)
{
return distance < r.distance;
}
} RenderListEntry;
private:
void renderStars(const StarDatabase& starDB,
const VisibleStarSet& visset,
const Observer& observer);
void renderPlanetarySystem(const Star& sun,
const PlanetarySystem& solSystem,
const Observer& observer,
Mat4d& frame,
double now,
bool showLabels = false);
void renderPlanet(const Body& body,
Point3f pos,
Vec3f sunDirection,
float distance,
float appMag,
double now,
Quatf orientation);
void renderStar(const Star& star,
Point3f pos,
float distance,
float appMag,
Quatf orientation);
void renderBodyAsParticle(Point3f center,
float appMag,
float discSizeInPixels,
Color color,
const Quatf& orientation,
bool useHaloes);
void labelStars(const vector<Star*>& stars,
const StarDatabase& starDB,
const Observer& observer);
void renderParticles(const vector<Particle>& particles,
Quatf orientation);
void renderLabels();
private:
int windowWidth;
int windowHeight;
float fov;
float pixelSize;
TextureManager* textureManager;
MeshManager* meshManager;
Console* console;
int renderMode;
int labelMode;
float ambientLightLevel;
vector<RenderListEntry> renderList;
vector<Particle> starParticles;
vector<Particle> glareParticles;
vector<Particle> planetParticles;
vector<Label> labels;
vector<Star*> labelledStars;
double modelMatrix[16];
double projMatrix[16];
int nSimultaneousTextures;
public:
friend bool operator<(const Renderer::RenderListEntry&,
const Renderer::RenderListEntry&);
};
#if 0
class Renderer::ParticleList
{
private:
vector<Particle> particles;
public:
ParticleList() {};
void clear() { particles.clear(); };
void addParticle(Particle& p) { particles.insert(particles.end(), p); };
void render(Quatf orientation);
};
class Renderer::RenderList
{
private:
vector<RenderListEntry> renderables;
public:
RenderList() {};
void clear() { renderables.clear(); };
void add(Body*, Point3f, Vec3f, float);
void render(double, Quatf, float, TextureManager*);
friend bool operator<(RenderListEntry&, RenderListEntry&);
};
#endif
#endif // _RENDER_H_

60
src/resmanager.cpp 100644
View File

@ -0,0 +1,60 @@
// resmanager.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "resmanager.h"
using namespace std;
ResourceManager::ResourceManager() : baseDir("")
{
}
ResourceManager::ResourceManager(string _baseDir) : baseDir(_baseDir)
{
}
ResourceManager::ResourceManager(char* _baseDir) : baseDir(_baseDir)
{
}
ResourceManager::~ResourceManager()
{
// TODO: Clean up
}
// If the named resource has already been loaded, return a pointer to it
// in res and return true. Otherwise, leave res untouched and return false.
// find() can be safely called with res == NULL just to test whether or not
// the resource is resident.
bool ResourceManager::findResource(string name, void** res)
{
ResourceTable::iterator iter = resources.find(name);
if (iter != resources.end())
{
if (res != NULL)
*res = iter->second;
return true;
}
else
{
return false;
}
}
void ResourceManager::addResource(string name, void* res)
{
resources.insert(ResourceTable::value_type(name, res));
}

38
src/resmanager.h 100644
View File

@ -0,0 +1,38 @@
// resmanager.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _RESMANAGER_H_
#define _RESMANAGER_H_
#include <string>
#include <map>
#include "texture.h"
class ResourceManager
{
public:
ResourceManager();
ResourceManager(string _baseDir);
ResourceManager(char* _baseDir);
~ResourceManager();
protected:
bool findResource(string name, void**);
void addResource(string name, void*);
string baseDir;
private:
typedef std::map<string, void*> ResourceTable;
ResourceTable resources;
};
#endif // _RESMANAGER_H_

45
src/rng.cpp 100644
View File

@ -0,0 +1,45 @@
// rng.cpp
#include <stdlib.h>
#include "celestia.h"
#include "rng.h"
static const uint32 gen = 1423130227u;
RandomNumberGenerator::RandomNumberGenerator() : state(0)
{
}
RandomNumberGenerator::RandomNumberGenerator(uint32) : state(s)
{
}
void RandomNumberGenerator::seed(long s)
{
state = s;
}
RandomNumberGenerator::randomInt()
{
state = gen * state + gen * 2;
return state;
}
double RandomNumberGenerator::randomDouble()
{
return (double) randomInt() / (double) ~((uint32) 1);
}
float RandomNumberGenerator::randomFloat()
{
// Use randomDouble() in order to avoid round off errors that may result
// from casting large integer values to floats.
return (float) randomDouble();
}

22
src/rng.h 100644
View File

@ -0,0 +1,22 @@
// rng.h
#ifndef _RNG_H_
#define _RNG_H_
class RandomNumberGenerator
{
public:
RandomNumberGenerator();
RandomNumberGenerator(long s);
void seed(long);
uint32 randomInt();
float randomFloat();
double randomeDouble();
private:
uint32 state;
};
#endif // _RNG_H_

32
src/selection.h 100644
View File

@ -0,0 +1,32 @@
// selection.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _SELECTION_H_
#define _SELECTION_H_
class Selection
{
public:
Selection() : star(NULL), body(NULL) {};
Selection(Star* _star) : star(_star), body(NULL) {};
Selection(Body* _body) : star(NULL), body(_body) {};
~Selection() {};
bool empty() { return star == NULL && body == NULL; };
Star* star;
Body* body;
};
inline bool operator==(const Selection& s0, const Selection& s1)
{
return s0.star == s1.star && s0.body == s1.body;
}
#endif // _SELECTION_H_

821
src/simulation.cpp 100644
View File

@ -0,0 +1,821 @@
// simulation.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// The core of Celestia--tracks an observer moving through a
// stars and their solar systems.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <algorithm>
#include "mathlib.h"
#include "vecmath.h"
#include "perlin.h"
#include "astro.h"
#include "simulation.h"
using namespace std;
#define VELOCITY_CHANGE_TIME 1.0f
Simulation::Simulation() :
realTime(0.0),
simTime(0.0),
timeScale(1.0),
typedText(""),
stardb(NULL),
solarSystemCatalog(NULL),
visibleStars(NULL),
closestSolarSystem(NULL),
selection(),
targetSpeed(0.0),
targetVelocity(0.0, 0.0, 0.0),
initialVelocity(0.0, 0.0, 0.0),
beginAccelTime(0.0),
observerMode(Free),
hudDetail(1)
{
}
Simulation::~Simulation()
{
// TODO: Clean up!
}
static void displayDistance(Console& console, double distance)
{
if (distance >= astro::AUtoLightYears(1000.0f))
console.printf("%.3f ly", distance);
else if (distance >= astro::kilometersToLightYears(10000000.0))
console.printf("%.3f au", astro::lightYearsToAU(distance));
else
console.printf("%.3f km", astro::lightYearsToKilometers(distance));
}
static void displayStarInfo(Console& console,
Star& star,
StarDatabase& starDB,
double distance)
{
StarNameDatabase* starNameDB = starDB.getNameDatabase();
// Print the star name and designations
StarNameDatabase::iterator iter = starNameDB->find(star.getCatalogNumber());
if (iter != starNameDB->end())
{
StarName* starName = iter->second;
if (starName->getName() != "")
console << starName->getName() << " / ";
Constellation* constellation = starName->getConstellation();
if (constellation != NULL)
console << starName->getDesignation() << ' ' << constellation->getGenitive() << " / ";
}
if ((star.getCatalogNumber() & 0xf0000000) == 0)
console << "HD " << star.getCatalogNumber() << '\n';
else
console << "HIP " << (star.getCatalogNumber() & 0x0fffffff) << '\n';
console.printf("Abs (app) mag = %.2f (%.2f)\n",
star.getAbsoluteMagnitude(),
astro::absToAppMag(star.getAbsoluteMagnitude(), (float) distance));
console << "Class: " << star.getStellarClass() << '\n';
console.printf("Radius: %.2f Rsun\n", star.getRadius() / 696000.0f);
}
static void displayPlanetInfo(Console& console,
Body& body,
double distance)
{
console << body.getName() << '\n';
console << "Radius: " << body.getRadius() << " km\n";
console << "Day length: " << body.getRotationPeriod() << " hours\n";
}
void Simulation::displaySelectionInfo(Console& console)
{
if (selection.star != NULL)
{
Vec3d v = astro::universalPosition(Point3d(0, 0, 0), selection.star->getPosition()) -
observer.getPosition();
console << "Distance to target: ";
displayDistance(console, v.length());
console << '\n';
displayStarInfo(console, *selection.star, *stardb, v.length());
}
else if (selection.body != NULL)
{
uint32 starNumber = Star::InvalidStar;
if (selection.body->getSystem() != NULL)
starNumber = selection.body->getSystem()->getStarNumber();
Star *star = stardb->find(starNumber);
if (star != NULL)
{
Vec3d v = astro::universalPosition(selection.body->getHeliocentricPosition(simTime / 86400.0), star->getPosition()) - observer.getPosition();
console << "Distance to target: ";
displayDistance(console, v.length());
console << '\n';
displayPlanetInfo(console, *selection.body, v.length());
}
}
}
void Simulation::render(Renderer& renderer)
{
Console* console = renderer.getConsole();
console->clear();
console->home();
if (hudDetail > 0)
{
console->printf("Visible stars = %d\n", visibleStars->getVisibleSet()->size());
// Display the velocity
{
double v = observer.getVelocity().length();
char* units;
if (v < astro::AUtoLightYears(1000))
{
if (v < astro::kilometersToLightYears(10000000.0f))
{
v = astro::lightYearsToKilometers(v);
units = "km/s";
}
else
{
v = astro::lightYearsToAU(v);
units = "AU/s";
}
}
else
{
units = "ly/s";
}
console->printf("Speed: %f %s\n", v, units);
}
// Display the date
*console << astro::Date(simTime / 86400.0) << '\n';
displaySelectionInfo(*console);
*console << typedText;
}
renderer.render(observer,
*stardb,
*visibleStars,
closestSolarSystem,
selection,
simTime);
}
static Quatf lookAt(Point3f from, Point3f to, Vec3f up)
{
Vec3f n = from - to;
n.normalize();
Vec3f v = up ^ n;
v.normalize();
Mat4f r = Mat4f::rotation(v, (float) PI / 2);
Vec3f u = n * r;
return ~Quatf(Mat3f(v, u, n));
}
SolarSystem* Simulation::getSolarSystem(Star* star)
{
uint32 starNum = star->getCatalogNumber();
SolarSystemCatalog::iterator iter = solarSystemCatalog->find(starNum);
if (iter == solarSystemCatalog->end())
return NULL;
else
return iter->second;
}
Star* Simulation::getSun(Body* body)
{
PlanetarySystem* system = body->getSystem();
if (system == NULL)
return NULL;
else
return stardb->find(system->getStarNumber());
}
UniversalCoord Simulation::getSelectionPosition(Selection& sel, double when)
{
if (sel.body != NULL)
{
Point3f sunPos(0.0f, 0.0f, 0.0f);
Star* sun = getSun(sel.body);
if (sun != NULL)
sunPos = sun->getPosition();
return astro::universalPosition(sel.body->getHeliocentricPosition(when / 86400.0),
sunPos);
}
else if (sel.star != NULL)
{
return astro::universalPosition(Point3d(0.0, 0.0, 0.0), sel.star->getPosition());
}
else
{
return UniversalCoord(Point3d(0.0, 0.0, 0.0));
}
}
float getSelectionSize(Selection& sel)
{
if (sel.body != NULL)
return sel.body->getRadius();
else if (sel.star != NULL)
return sel.star->getRadius();
else
return 0.0f;
}
void Simulation::setStarDatabase(StarDatabase* db,
SolarSystemCatalog* catalog)
{
stardb = db;
solarSystemCatalog = catalog;
if (visibleStars != NULL)
{
delete visibleStars;
visibleStars = NULL;
}
if (db != NULL)
{
visibleStars = new VisibleStarSet(stardb);
visibleStars->setLimitingMagnitude(5.0f);
visibleStars->setCloseDistance(10.0f);
visibleStars->updateAll(observer);
}
}
// Set the time in seconds from J2000
void Simulation::setTime(double t)
{
simTime = t;
}
void Simulation::update(double dt)
{
realTime += dt;
simTime += dt * timeScale;
if (observerMode == Travelling)
{
float t = clamp((realTime - journey.startTime) / journey.duration);
// Smooth out the linear interpolation of position
float u = (float) sin(sin(t * PI / 2) * PI / 2);
Vec3d jv = journey.to - journey.from;
UniversalCoord p = journey.from + jv * (double) u;
// Interpolate the orientation using lookAt()
// We gradually change the focus point for lookAt() from the initial
// focus to the destination star over the first half of the journey
Vec3d lookDir0 = journey.initialFocus - journey.from;
Vec3d lookDir1 = journey.finalFocus - journey.to;
lookDir0.normalize();
lookDir1.normalize();
Vec3d lookDir;
if (t < 0.5f)
{
// Smooth out the interpolation of the focus point to avoid
// jarring changes in orientation
double v = sin(t * PI);
double c = lookDir0 * lookDir1;
double angle = acos(c);
if (c >= 1.0 || angle < 1.0e-6)
{
lookDir = lookDir0;
}
else
{
double s = sin(angle);
double is = 1.0 / s;
// Spherically interpolate the look direction between the
// intial and final directions.
lookDir = lookDir0 * (sin((1 - v) * angle) * is) +
lookDir1 * (sin(v * angle) * is);
// Linear interpolation wasn't such a good idea . . .
// lookDir = lookDir0 + (lookDir1 - lookDir0) * v;
}
}
else
{
lookDir = lookDir1;
}
observer.setOrientation(lookAt(Point3f(0, 0, 0),
Point3f((float) lookDir.x,
(float) lookDir.y,
(float) lookDir.z),
journey.up));
observer.setPosition(p);
// If the journey's complete, reset to manual control
if (t == 1.0f)
{
observer.setPosition(journey.to);
observerMode = Free;
observer.setVelocity(Vec3d(0, 0, 0));
targetVelocity = Vec3d(0, 0, 0);
}
}
else if (observerMode == Following)
{
Point3d posRelToSun = followInfo.body->getHeliocentricPosition(simTime / 86400.0) + followInfo.offset;
observer.setPosition(astro::universalPosition(posRelToSun,
followInfo.sun->getPosition()));
}
else
{
if (observer.getVelocity() != targetVelocity)
{
double t = clamp((realTime - beginAccelTime) / VELOCITY_CHANGE_TIME);
observer.setVelocity(observer.getVelocity() * (1.0 - t) +
targetVelocity * t);
}
observer.update(dt);
}
if (visibleStars != NULL)
visibleStars->update(observer, 0.05f);
// Find the closest solar system
Point3f observerPos = (Point3f) observer.getPosition();
vector<uint32>* closeStars = visibleStars->getCloseSet();
for (int i = 0; i < closeStars->size(); i++)
{
uint32 starIndex = (*closeStars)[i];
Star* star = stardb->getStar(starIndex);
if (observerPos.distanceTo(star->getPosition()) < 1.0f)
{
SolarSystem* solarSystem = getSolarSystem(star);
if (solarSystem != NULL)
closestSolarSystem = solarSystem;
}
}
}
Selection Simulation::getSelection() const
{
return selection;
}
void Simulation::setSelection(const Selection& sel)
{
selection = sel;
}
struct PlanetPickInfo
{
float cosClosestAngle;
Body* closestBody;
Vec3d direction;
Point3d origin;
double jd;
};
bool PlanetPickTraversal(Body* body, void* info)
{
PlanetPickInfo* pickInfo = (PlanetPickInfo*) info;
Point3d bpos = body->getHeliocentricPosition(pickInfo->jd);
Vec3d bodyDir = bpos - pickInfo->origin;
bodyDir.normalize();
double cosAngle = bodyDir * pickInfo->direction;
if (cosAngle > pickInfo->cosClosestAngle)
{
pickInfo->cosClosestAngle = cosAngle;
pickInfo->closestBody = body;
}
return true;
}
Selection Simulation::pickPlanet(Observer& observer,
Star& sun,
SolarSystem& solarSystem,
Vec3f pickRay)
{
PlanetPickInfo pickInfo;
// Transform the pick direction
pickRay = pickRay * observer.getOrientation().toMatrix4();
pickInfo.direction = Vec3d((double) pickRay.x,
(double) pickRay.y,
(double) pickRay.z);
pickInfo.origin = astro::heliocentricPosition(observer.getPosition(),
sun.getPosition());
pickInfo.cosClosestAngle = -1.0f;
pickInfo.closestBody = NULL;
pickInfo.jd = simTime / 86400.0f;
solarSystem.getPlanets()->traverse(PlanetPickTraversal, (void*) &pickInfo);
if (pickInfo.cosClosestAngle > cos(degToRad(0.5f)))
selection = Selection(pickInfo.closestBody);
else
selection = Selection();
return selection;
}
Selection Simulation::pickStar(Vec3f pickRay)
{
// Transform the pick direction
pickRay = pickRay * observer.getOrientation().toMatrix4();
Point3f observerPos = (Point3f) observer.getPosition();
vector<uint32>* vis = visibleStars->getVisibleSet();
int nStars = vis->size();
float cosAngleClosest = -1.0f;
int closest = -1;
for (int i = 0; i < nStars; i++)
{
int starIndex = (*vis)[i];
Star* star = stardb->getStar(starIndex);
Vec3f starDir = star->getPosition() - observerPos;
starDir.normalize();
float cosAngle = starDir * pickRay;
if (cosAngle > cosAngleClosest)
{
cosAngleClosest = cosAngle;
closest = starIndex;
}
}
if (cosAngleClosest > cos(degToRad(0.5f)))
{
selection = Selection(stardb->getStar(closest));
}
else
{
selection = Selection();
}
return selection;
}
Selection Simulation::pickObject(Vec3f pickRay)
{
Point3f observerPos = (Point3f) observer.getPosition();
vector<uint32>* closeStars = visibleStars->getCloseSet();
for (int i = 0; i < closeStars->size(); i++)
{
uint32 starIndex = (*closeStars)[i];
Star* star = stardb->getStar(starIndex);
if (observerPos.distanceTo(star->getPosition()) < 1.0f)
{
SolarSystem* solarSystem = getSolarSystem(star);
if (solarSystem != NULL)
{
pickPlanet(observer, *star, *solarSystem, pickRay);
}
}
}
if (selection.body == NULL)
return pickStar(pickRay);
else
return selection;
}
void Simulation::computeGotoParameters(Selection& destination, JourneyParams& jparams)
{
UniversalCoord targetPosition = getSelectionPosition(selection, simTime);
Vec3d v = targetPosition - observer.getPosition();
double distanceToTarget = v.length();
double maxOrbitDistance = (selection.body != NULL) ? astro::kilometersToLightYears(5.0f * selection.body->getRadius()) : 0.5f;
double orbitDistance = (distanceToTarget > maxOrbitDistance * 10.0f) ? maxOrbitDistance : distanceToTarget * 0.1f;
v.normalize();
// TODO: This should be an option someplace
jparams.duration = 5.0f;
jparams.startTime = realTime;
// Right where we are now . . .
jparams.from = observer.getPosition();
// The destination position lies along the line between the current
// position and the star
jparams.to = targetPosition - v * orbitDistance;
jparams.initialFocus = jparams.from +
(Vec3f(0, 0, -1.0f) * observer.getOrientation().toMatrix4());
jparams.finalFocus = targetPosition;
jparams.up = Vec3f(0, 1, 0) * observer.getOrientation().toMatrix4();
}
void Simulation::computeCenterParameters(Selection& destination, JourneyParams& jparams)
{
UniversalCoord targetPosition = getSelectionPosition(selection, simTime);
// TODO: This should be an option someplace
jparams.duration = 0.5f;
jparams.startTime = realTime;
// Don't move through space, just rotate the camera
jparams.from = observer.getPosition();
jparams.to = jparams.from;
jparams.initialFocus = jparams.from +
(Vec3f(0, 0, -1.0f) * observer.getOrientation().toMatrix4());
jparams.finalFocus = targetPosition;
jparams.up = Vec3f(0, 1, 0) * observer.getOrientation().toMatrix4();
}
void Simulation::applyForce(Vec3f force, float dt)
{
Vec3d f(force.x * dt, force.y * dt, force.z * dt);
observer.setVelocity(observer.getVelocity() + f);
}
void Simulation::applyForceRelativeToOrientation(Vec3f force, float dt)
{
applyForce(force * observer.getOrientation().toMatrix4(), dt);
}
Quatf Simulation::getOrientation()
{
return observer.getOrientation();
}
void Simulation::setOrientation(Quatf q)
{
observer.setOrientation(q);
}
// Orbit around the selection (if there is one.) This involves changing
// both the observer's position and orientation.
void Simulation::orbit(Quatf q)
{
if (selection.body != NULL || selection.star != NULL)
{
UniversalCoord focusPosition = getSelectionPosition(selection, simTime);
Vec3d v = observer.getPosition() - focusPosition;
double distance = v.length();
Mat3f m = conjugate(observer.getOrientation()).toMatrix3();
// Convert the matrix to double precision so we can multiply it
// by the double precision vector. Yuck. VC doesn't seem to
// be able to figure out that the constructor declared in
// vecmath.h should allow: md = m
Mat3d md;
md[0][0] = m[0][0]; md[0][1] = m[0][1]; md[0][2] = m[0][2];
md[1][0] = m[1][0]; md[1][1] = m[1][1]; md[1][2] = m[1][2];
md[2][0] = m[2][0]; md[2][1] = m[2][1]; md[2][2] = m[2][2];
v = v * md;
observer.setOrientation(observer.getOrientation() * q);
m = observer.getOrientation().toMatrix3();
md[0][0] = m[0][0]; md[0][1] = m[0][1]; md[0][2] = m[0][2];
md[1][0] = m[1][0]; md[1][1] = m[1][1]; md[1][2] = m[1][2];
md[2][0] = m[2][0]; md[2][1] = m[2][1]; md[2][2] = m[2][2];
v = v * md;
// Roundoff errors will accumulate and cause the distance between
// viewer and focus to change unless we take steps to keep the
// length of v constant.
v.normalize();
v *= distance;
observer.setPosition(focusPosition + v);
}
}
// Exponential camera dolly--move toward or away from the selected object
// at a rate dependent on the observer's distance from the object.
void Simulation::changeOrbitDistance(float d)
{
if (selection.body != NULL || selection.star != NULL)
{
UniversalCoord focusPosition = getSelectionPosition(selection, simTime);
double size = getSelectionSize(selection);
// Somewhat arbitrary parameters to chosen to give the camera movement
// a nice feel. They should probably be function parameters.
double minOrbitDistance = astro::kilometersToLightYears(1.05 * size);
double naturalOrbitDistance = astro::kilometersToLightYears(4.0 * size);
// Determine distance and direction to the selected object
Vec3d v = observer.getPosition() - focusPosition;
double currentDistance = v.length();
if (currentDistance >= minOrbitDistance && naturalOrbitDistance != 0)
{
double r = (currentDistance - minOrbitDistance) / naturalOrbitDistance;
double newDistance = minOrbitDistance + naturalOrbitDistance * exp(log(r) + d);
v = v * (newDistance / currentDistance);
observer.setPosition(focusPosition + v);
}
}
}
void Simulation::setTargetSpeed(float s)
{
targetSpeed = s;
Vec3f v = Vec3f(0, 0, -s) * observer.getOrientation().toMatrix4();
targetVelocity = Vec3d(v.x, v.y, v.z);
initialVelocity = observer.getVelocity();
beginAccelTime = realTime;
}
float Simulation::getTargetSpeed()
{
return targetSpeed;
}
void Simulation::gotoSelection()
{
if (selection.body != NULL || selection.star != NULL)
{
computeGotoParameters(selection, journey);
observerMode = Travelling;
}
}
void Simulation::centerSelection()
{
if (selection.body != NULL || selection.star != NULL)
{
computeCenterParameters(selection, journey);
observerMode = Travelling;
}
}
void Simulation::follow()
{
if (observerMode == Following)
{
observerMode = Free;
}
else
{
if (selection.body != NULL)
{
Star* sun = getSun(selection.body);
if (sun != NULL)
{
observerMode = Following;
followInfo.sun = sun;
followInfo.body = selection.body;
Point3d planetPos = selection.body->getHeliocentricPosition(simTime / 86400.0);
Point3d observerPos = astro::heliocentricPosition(observer.getPosition(),
sun->getPosition());
followInfo.offset = observerPos - planetPos;
}
}
}
}
void Simulation::selectStar(uint32 catalogNo)
{
selection = Selection(stardb->find(catalogNo));
}
void Simulation::selectPlanet(int index)
{
if (index < 0)
{
if (selection.body != NULL)
{
PlanetarySystem* system = selection.body->getSystem();
if (system != NULL)
selectStar(system->getStarNumber());
}
}
else
{
Star* star = NULL;
if (selection.star != NULL)
{
star = selection.star;
}
else if (selection.body != NULL)
{
star = getSun(selection.body);
}
SolarSystem* solarSystem = NULL;
if (star != NULL)
solarSystem = getSolarSystem(star);
else
solarSystem = closestSolarSystem;
if (solarSystem != NULL && index < solarSystem->getPlanets()->getSystemSize())
selection = Selection(solarSystem->getPlanets()->getBody(index));
}
}
void Simulation::selectBody(string s)
{
Star* star = stardb->find(s);
if (star != NULL)
{
selectStar(star->getCatalogNumber());
}
else if (closestSolarSystem != NULL)
{
Body* body = closestSolarSystem->getPlanets()->find(s, true);
if (body != NULL)
selection = Selection(body);
}
}
void Simulation::typeChar(char c)
{
if (c == '\n')
{
selectBody(typedText);
typedText = "";
}
else
{
typedText += c;
}
}
double Simulation::getTimeScale()
{
return timeScale;
}
void Simulation::setTimeScale(double _timeScale)
{
timeScale = _timeScale;
}
int Simulation::getHUDDetail() const
{
return hudDetail;
}
void Simulation::setHUDDetail(int detail)
{
hudDetail = detail;
}
SolarSystem* Simulation::getNearestSolarSystem() const
{
return closestSolarSystem;
}

150
src/simulation.h 100644
View File

@ -0,0 +1,150 @@
// simulation.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _SIMULATION_H_
#define _SIMULATION_H_
#include <vector>
#include "vecmath.h"
#include "quaternion.h"
#include "texture.h"
#include "console.h"
#include "mesh.h"
#include "stardb.h"
#include "visstars.h"
#include "solarsys.h"
#include "texmanager.h"
#include "render.h"
class Simulation
{
public:
Simulation();
~Simulation();
void setTime(double t); // Time in seconds
void update(double dt);
void render(Renderer&);
Selection pickObject(Vec3f pickRay);
void setStarDatabase(StarDatabase* db,
SolarSystemCatalog* catalog);
// Methods for moving the observer
// TODO: Fix up this ancient and stupid interface
void applyForce(Vec3f force, float dt);
void applyForceRelativeToOrientation(Vec3f force, float dt);
Quatf getOrientation();
void setOrientation(Quatf q);
void orbit(Quatf q);
void changeOrbitDistance(float d);
void setTargetSpeed(float s);
float getTargetSpeed();
Selection getSelection() const;
void setSelection(const Selection&);
void selectStar(uint32);
void selectPlanet(int);
void selectBody(string s);
void gotoSelection();
void centerSelection();
void follow();
SolarSystem* getNearestSolarSystem() const;
void setTimeScale(double);
double getTimeScale();
int getHUDDetail() const;
void setHUDDetail(int);
void typeChar(char c);
enum ObserverMode {
Free = 0,
Travelling = 1,
Following = 2,
Tracking = 3,
};
void setObserverMode(ObserverMode);
ObserverMode getObserverMode() const;
private:
// Class-specific types
typedef struct
{
double duration;
double startTime;
UniversalCoord from;
UniversalCoord to;
UniversalCoord initialFocus;
UniversalCoord finalFocus;
Vec3f up;
} JourneyParams;
typedef struct
{
Body* body;
Star* sun;
Vec3d offset;
} FollowParams;
private:
SolarSystem* getSolarSystem(Star* star);
Star* getSun(Body* body);
UniversalCoord getSelectionPosition(Selection& sel, double when);
Selection pickPlanet(Observer& observer,
Star& sun,
SolarSystem& solarSystem,
Vec3f pickRay);
Selection pickStar(Vec3f pickRay);
void computeGotoParameters(Selection& sel, JourneyParams& jparams);
void computeCenterParameters(Selection& sel, JourneyParams& jparams);
void displaySelectionInfo(Console&);
private:
double realTime;
double simTime;
double timeScale;
string typedText;
StarDatabase* stardb;
SolarSystemCatalog* solarSystemCatalog;
VisibleStarSet* visibleStars;
SolarSystem* closestSolarSystem;
Star* selectedStar;
Body* selectedBody;
Selection selection;
int selectedPlanet;
Observer observer;
double targetSpeed;
Vec3d targetVelocity;
Vec3d initialVelocity;
double beginAccelTime;
ObserverMode observerMode;
bool travelling;
bool following;
JourneyParams journey;
FollowParams followInfo;
int hudDetail;
};
#endif // SIMULATION_H_

13
src/slurp.c 100644
View File

@ -0,0 +1,13 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = stdin;
char buf[256];
for (;;) {
fgets(buf, sizeof(buf), fp);
}
}

444
src/solarsys.cpp 100644
View File

@ -0,0 +1,444 @@
// solarsys.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "mathlib.h"
#include "astro.h"
#include "parser.h"
#include "solarsys.h"
typedef struct
{
char *name;
float radius;
float obliquity;
float albedo;
double period;
double semiMajorAxis;
double eccentricity;
double inclination;
double ascendingNode;
double argOfPeriapsis;
double trueAnomaly;
} Planet;
Planet SolSystem[] =
{
{ "Mercury", 2440, 7.0f, 0.06f,
0.2408, 0.3871, 0.2056, 7.0049, 77.456, 48.331, 252.251 },
{ "Venus", 6052, 177.4f, 0.77f,
0.6152, 0.7233, 0.0068, 3.3947, 131.533, 76.681, 181.979 },
{ "Earth", 6378, 23.45f, 0.30f,
1.0000, 1.0000, 0.0167, 0.0001, 102.947, 348.739, 100.464 },
{ "Mars", 3394, 23.98f, 0.15f,
1.8809, 1.5237, 0.0934, 1.8506, 336.041, 49.579, 355.453 },
{ "Jupiter", 71398, 3.08f, 0.51f,
11.8622, 5.2034, 0.0484, 1.3053, 14.7539, 100.556, 34.404 },
{ "Saturn", 60330, 26.73f, 0.50f,
29.4577, 9.5371, 0.0542, 2.4845, 92.432, 113.715, 49.944 },
{ "Uranus", 26200, 97.92f, 0.66f,
84.0139, 19.1913, 0.0472, 0.7699, 170.964, 74.230, 313.232 },
{ "Neptune", 25225, 28.8f, 0.62f,
164.793, 30.0690, 0.0086, 1.7692, 44.971, 131.722, 304.880 },
{ "Pluto", 1137, 122.46f, 0.6f,
248.54, 39.4817, 0.2488, 17.142, 224.067, 110.303, 238.928 },
};
static Body* createSatellite(Planet* p)
{
EllipticalOrbit* orbit = new EllipticalOrbit(astro::AUtoKilometers(p->semiMajorAxis),
p->eccentricity,
degToRad(p->inclination),
degToRad(p->ascendingNode),
degToRad(p->argOfPeriapsis),
degToRad(p->trueAnomaly),
p->period * 365.25f);
Body* body = new Body(NULL);
body->setName(string(p->name));
body->setOrbit(orbit);
body->setRadius(p->radius);
body->setObliquity(degToRad(p->obliquity));
body->setAlbedo(p->albedo);
return body;
}
// Create a solar system with our nine familiar planets
SolarSystem* CreateOurSolarSystem()
{
SolarSystem* solarSystem = new SolarSystem(0);
for (int i = 0; i < sizeof(SolSystem) / sizeof(SolSystem[0]); i++)
{
solarSystem->getPlanets()->addBody(createSatellite(&SolSystem[i]));
}
return solarSystem;
}
// Create a body (planet or moon) using the values from a hash
// The usePlanetsUnits flags specifies whether period and semi-major axis
// are in years and AU rather than days and kilometers
static Body* CreatePlanet(PlanetarySystem* system,
Hash* planetData,
bool usePlanetUnits = true)
{
Body* body = new Body(system);
string name("Unnamed");
planetData->getString("Name", name);
body->setName(name);
cout << "Reading planet " << name << "\n";
double semiMajorAxis = 0.0;
if (!planetData->getNumber("SemiMajorAxis", semiMajorAxis))
{
cout << "SemiMajorAxis missing! Skipping planet . . .\n";
delete body;
return NULL;
}
double period = 0.0;
if (!planetData->getNumber("Period", period))
{
cout << "Period missing! Skipping planet . . .\n";
delete body;
return NULL;
}
double eccentricity = 0.0;
planetData->getNumber("Eccentricity", eccentricity);
double inclination = 0.0;
planetData->getNumber("Inclination", inclination);
double ascendingNode = 0.0;
planetData->getNumber("AscendingNode", ascendingNode);
double argOfPeriapsis = 0.0;
planetData->getNumber("ArgOfPeriapsis", argOfPeriapsis);
double trueAnomaly = 0.0;
planetData->getNumber("TrueAnomaly", trueAnomaly);
if (usePlanetUnits)
{
semiMajorAxis = astro::AUtoKilometers(semiMajorAxis);
period = period * 265.25f;
}
body->setOrbit(new EllipticalOrbit(semiMajorAxis,
eccentricity,
degToRad(inclination),
degToRad(ascendingNode),
degToRad(argOfPeriapsis),
degToRad(trueAnomaly),
period));
double obliquity = 0.0;
planetData->getNumber("Obliquity", obliquity);
body->setObliquity(degToRad(obliquity));
double albedo = 0.5;
planetData->getNumber("Albedo", albedo);
body->setAlbedo(albedo);
double radius = 10000.0;
planetData->getNumber("Radius", radius);
body->setRadius(radius);
double oblateness = 0.0;
planetData->getNumber("Oblateness", oblateness);
body->setOblateness(oblateness);
// The default rotation period is the same as the orbital period
double rotationPeriod = period * 24.0;
planetData->getNumber("RotationPeriod", rotationPeriod);
body->setRotationPeriod(rotationPeriod);
Color color(1.0f, 1.0f, 1.0f);
planetData->getColor("Color", color);
body->setColor(color);
string texture("");
planetData->getString("Texture", texture);
body->setTexture(texture);
string mesh("");
planetData->getString("Mesh", mesh);
body->setMesh(mesh);
bool blendTexture = false;
planetData->getBoolean("BlendTexture", blendTexture);
body->setAppearanceFlag(Body::BlendTexture, blendTexture);
// Read the ring system
{
Value* ringsDataValue = planetData->getValue("Rings");
if (ringsDataValue != NULL)
{
if (ringsDataValue->getType() != Value::HashType)
{
cout << "ReadSolarSystem: Rings must be an assoc array.\n";
}
else
{
Hash* ringsData = ringsDataValue->getHash();
// ASSERT(ringsData != NULL);
double inner = 0.0, outer = 0.0;
ringsData->getNumber("Inner", inner);
ringsData->getNumber("Outer", outer);
Color color(1.0f, 1.0f, 1.0f);
ringsData->getColor("Color", color);
body->setRings(RingSystem((float) inner, (float) outer,
color));
}
}
}
// Read the moons
// TODO: This is largely cut-and-pasted from the ReadSolarSystem function
// It would be better if they actually used the same code
Value* moonsDataValue = planetData->getValue("Moons");
if (moonsDataValue != NULL)
{
if (moonsDataValue->getType() != Value::ArrayType)
{
cout << "ReadSolarSystem: Moons must be an array.\n";
}
else
{
Array* moonsData = moonsDataValue->getArray();
// ASSERT(moonsData != NULL);
PlanetarySystem* satellites = NULL;
if (moonsData->size() != 0)
satellites = new PlanetarySystem(body);
for (int i = 0; i < moonsData->size(); i++)
{
Value* moonValue = (*moonsData)[i];
if (moonValue != NULL &&
moonValue->getType() == Value::HashType)
{
Body* moon = CreatePlanet(satellites,
moonValue->getHash(),
false);
if (moon != NULL)
satellites->addBody(moon);
}
else
{
cout << "ReadSolarSystem: Moon data must be an assoc array.\n";
}
}
body->setSatellites(satellites);
}
}
return body;
}
static SolarSystem* ReadSolarSystem(Parser& parser,
const StarDatabase& starDB)
{
Value* starName = parser.readValue();
if (starName == NULL)
{
cout << "ReadSolarSystem: Error reading star name.\n";
return NULL;
}
if (starName->getType() != Value::StringType)
{
cout << "ReadSolarSystem: Star name is not a string.\n";
delete starName;
return NULL;
}
Value* solarSystemDataValue = parser.readValue();
if (solarSystemDataValue == NULL)
{
cout << "ReadSolarSystem: Error reading solar system data\n";
delete starName;
return NULL;
}
if (solarSystemDataValue->getType() != Value::HashType)
{
cout << "ReadSolarSystem: Solar system data must be an assoc array\n";
delete starName;
delete solarSystemDataValue;
return NULL;
}
Hash* solarSystemData = solarSystemDataValue->getHash();
// ASSERT(solarSystemData != NULL);
Star* star = starDB.find(starName->getString());
if (star == NULL)
{
cout << "Cannot find star named '" << starName->getString() << "'\n";
delete starName;
delete solarSystemDataValue;
return NULL;
}
uint32 starNumber = star->getCatalogNumber();
SolarSystem* solarSys = new SolarSystem(starNumber);
Value* planetsDataValue = solarSystemData->getValue("Planets");
if (planetsDataValue != NULL)
{
if (planetsDataValue->getType() != Value::ArrayType)
{
cout << "ReadSolarSystem: Planets must be an array.\n";
}
else
{
Array* planetsData = planetsDataValue->getArray();
// ASSERT(planetsData != NULL);
for (int i = 0; i < planetsData->size(); i++)
{
Value* planetValue = (*planetsData)[i];
if (planetValue != NULL &&
planetValue->getType() == Value::HashType)
{
Body* body = CreatePlanet(solarSys->getPlanets(),
planetValue->getHash());
if (body != NULL)
solarSys->getPlanets()->addBody(body);
}
else
{
cout << "ReadSolarSystem: Planet data must be an assoc array.\n";
}
}
}
}
delete starName;
delete solarSystemDataValue;
return solarSys;
}
SolarSystemCatalog* ReadSolarSystemCatalog(istream& in,
StarDatabase& starDB)
{
Tokenizer tokenizer(&in);
Parser parser(&tokenizer);
SolarSystemCatalog* catalog = new SolarSystemCatalog();
while (tokenizer.nextToken() != Tokenizer::TokenEnd)
{
tokenizer.pushBack();
SolarSystem* solarSystem = ReadSolarSystem(parser, starDB);
if (solarSystem != NULL)
{
catalog->insert(SolarSystemCatalog::value_type(solarSystem->getStarNumber(),
solarSystem));
}
}
return catalog;
}
bool ReadSolarSystems(istream& in,
const StarDatabase& starDB,
SolarSystemCatalog& catalog)
{
Tokenizer tokenizer(&in);
Parser parser(&tokenizer);
while (tokenizer.nextToken() != Tokenizer::TokenEnd)
{
tokenizer.pushBack();
SolarSystem* solarSystem = ReadSolarSystem(parser, starDB);
if (solarSystem != NULL)
{
catalog.insert(SolarSystemCatalog::value_type(solarSystem->getStarNumber(),
solarSystem));
}
}
// TODO: Return some notification if there's an error parsring the file
return true;
}
SolarSystem::SolarSystem(uint32 _starNumber) : starNumber(_starNumber)
{
planets = new PlanetarySystem(starNumber);
}
uint32 SolarSystem::getStarNumber() const
{
return starNumber;
}
PlanetarySystem* SolarSystem::getPlanets() const
{
return planets;
}
#if 0
int SolarSystem::getSystemSize() const
{
return bodies.size();
}
Body* SolarSystem::getBody(int n) const
{
return bodies[n];
}
void SolarSystem::addBody(Body* sat)
{
bodies.insert(bodies.end(), sat);
}
Body* SolarSystem::find(string _name, bool deepSearch) const
{
for (int i = 0; i < bodies.size(); i++)
{
if (bodies[i]->getName() == _name)
{
return bodies[i];
}
else if (deepSearch && bodies[i]->getSatellites() != NULL)
{
Body* body = bodies[i]->getSatellites()->find(_name, deepSearch);
if (body != NULL)
return body;
}
}
return NULL;
}
#endif

42
src/solarsys.h 100644
View File

@ -0,0 +1,42 @@
// solarsys.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _SOLARSYS_H_
#define _SOLARSYS_H_
#include <vector>
#include <map>
#include <iostream>
#include "body.h"
#include "stardb.h"
class SolarSystem
{
public:
SolarSystem(uint32 _starNumber);
uint32 getStarNumber() const;
PlanetarySystem* getPlanets() const;
private:
PlanetarySystem* planets;
uint32 starNumber;
};
typedef std::map<uint32, SolarSystem*> SolarSystemCatalog;
SolarSystemCatalog* ReadSolarSystemCatalog(std::istream&, StarDatabase&);
bool ReadSolarSystems(std::istream&, const StarDatabase&, SolarSystemCatalog&);
// Mercury, Venus, Earth, etc.
SolarSystem* CreateOurSolarSystem();
#endif // _SOLARSYS_H_

328
src/spheremesh.cpp 100644
View File

@ -0,0 +1,328 @@
// mesh.cpp
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include "gl.h"
#include "mathlib.h"
#include "vecmath.h"
#include "spheremesh.h"
SphereMesh::SphereMesh(float radius, int _nRings, int _nSlices) :
vertices(NULL), normals(NULL), texCoords(NULL), indices(NULL)
{
createSphere(radius, _nRings, _nSlices);
}
SphereMesh::SphereMesh(Vec3f size, int _nRings, int _nSlices) :
vertices(NULL), normals(NULL), texCoords(NULL), indices(NULL)
{
createSphere(1.0f, _nRings, _nSlices);
scale(size);
}
SphereMesh::SphereMesh(Vec3f size,
const DisplacementMap& dispmap,
float height) :
vertices(NULL), normals(NULL), texCoords(NULL), indices(NULL)
{
createSphere(1.0f, dispmap.getHeight(), dispmap.getWidth());
scale(size);
displace(dispmap, height);
generateNormals();
fixNormals();
}
SphereMesh::SphereMesh(Vec3f size,
int _nRings, int _nSlices,
DisplacementMapFunc func,
void* info)
{
createSphere(1.0f, _nRings, _nSlices);
scale(size);
displace(func, info);
generateNormals();
fixNormals();
}
SphereMesh::~SphereMesh()
{
if (vertices != NULL)
delete[] vertices;
if (normals != NULL)
delete[] normals;
if (texCoords != NULL)
delete[] texCoords;
if (indices != NULL)
delete[] indices;
}
void SphereMesh::render()
{
if (vertices != NULL)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
}
if (normals != NULL)
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (texCoords != NULL)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDrawElements(GL_QUADS,
nIndices,
GL_UNSIGNED_SHORT,
indices);
}
void SphereMesh::createSphere(float radius, int _nRings, int _nSlices)
{
nRings = _nRings;
nSlices = _nSlices;
nVertices = nRings * (nSlices + 1);
vertices = new float[nVertices * 3];
normals = new float[nVertices * 3];
texCoords = new float[nVertices * 2];
nIndices = (nRings - 1) * nSlices * 4;
indices = new unsigned short[nIndices];
int i;
for (i = 0; i < nRings; i++)
{
float phi = ((float) i / (float) (nRings - 1) - 0.5f) * (float) PI;
for (int j = 0; j <= nSlices; j++)
{
float theta = (float) j / (float) nSlices * (float) PI * 2;
int n = i * (nSlices + 1) + j;
float x = (float) (cos(phi) * cos(theta));
float y = (float) sin(phi);
float z = (float) (cos(phi) * sin(theta));
vertices[n * 3] = x * radius;
vertices[n * 3 + 1] = y * radius;
vertices[n * 3 + 2] = z * radius;
normals[n * 3] = x;
normals[n * 3 + 1] = y;
normals[n * 3 + 2] = z;
texCoords[n * 2] = (float) j / (float) nSlices;
texCoords[n * 2 + 1] = (float) i / (float) (nRings - 1);
}
}
for (i = 0; i < nRings - 1; i++)
{
for (int j = 0; j < nSlices; j++)
{
int n = i * nSlices + j;
indices[n * 4 + 0] = i * (nSlices + 1) + j;
indices[n * 4 + 1] = (i + 1) * (nSlices + 1) + j;
indices[n * 4 + 2] = (i + 1) * (nSlices + 1) + j + 1;
indices[n * 4 + 3] = i * (nSlices + 1) + j + 1;
}
}
}
// Generate vertex normals for a quad mesh by averaging face normals
void SphereMesh::generateNormals()
{
Vec3f zero(0, 0, 0);
int nQuads = nIndices / 4;
Vec3f* faceNormals = new Vec3f[nQuads];
int i;
// Compute face normals for the mesh
for (i = 0; i < nQuads; i++)
{
float* p0 = vertices + indices[i * 4] * 3;
float* p1 = vertices + indices[i * 4 + 1] * 3;
float* p2 = vertices + indices[i * 4 + 2] * 3;
float* p3 = vertices + indices[i * 4 + 3] * 3;
// Compute the face normal. Watch out for degenerate (zero-length)
// edges. If there are two degenerate edges, the entire face must
// be degenerate and we'll handle that later
Vec3f v0(p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]);
Vec3f v1(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);
if (v0.length() < 1e-6f)
{
v0 = Vec3f(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);
v1 = Vec3f(p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);
}
else if (v1.length() < 1e-6f)
{
v0 = Vec3f(p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);
v1 = Vec3f(p0[0] - p3[0], p0[1] - p3[1], p0[2] - p3[2]);
}
Vec3f faceNormal = cross(v0, v1);
float length = faceNormal.length();
if (length != 0)
faceNormal *= (1 / length);
faceNormals[i] = faceNormal;
}
int* faceCounts = new int[nVertices];
for (i = 0; i < nVertices; i++)
{
faceCounts[i] = 0;
normals[i * 3] = 0;
normals[i * 3 + 1] = 0;
normals[i * 3 + 2] = 0;
}
for (i = 0; i < nIndices; i++)
{
int face = i / 4;
int vertex = indices[i];
faceCounts[vertex]++;
normals[vertex * 3] += faceNormals[face].x;
normals[vertex * 3 + 1] += faceNormals[face].y;
normals[vertex * 3 + 2] += faceNormals[face].z;
}
for (i = 0; i < nVertices; i++)
{
if (faceCounts[i] > 0)
{
float s = 1.0f / (float) faceCounts[i];
float nx = normals[i * 3] * s;
float ny = normals[i * 3 + 1] * s;
float nz = normals[i * 3 + 2] * s;
float length = (float) sqrt(nx * nx + ny * ny + nz * nz);
if (length > 0)
{
length = 1 / length;
normals[i * 3] = nx * length;
normals[i * 3 + 1] = ny * length;
normals[i * 3 + 2] = nz * length;
}
}
}
delete[] faceCounts;
delete[] faceNormals;
}
// Fix up the normals along the seam at longitude zero
void SphereMesh::fixNormals()
{
for (int i = 0; i < nRings; i++)
{
float* v0 = normals + (i * (nSlices + 1)) * 3;
float* v1 = normals + ((i + 1) * (nSlices + 1) - 1) * 3;
Vec3f n0(v0[0], v0[1], v0[2]);
Vec3f n1(v0[0], v0[1], v0[2]);
Vec3f normal = n0 + n1;
normal.normalize();
v0[0] = normal.x;
v0[1] = normal.y;
v0[2] = normal.z;
v1[0] = normal.x;
v1[1] = normal.y;
v1[2] = normal.z;
}
}
void SphereMesh::scale(Vec3f s)
{
int i;
for (i = 0; i < nVertices; i++)
{
vertices[i * 3] *= s.x;
vertices[i * 3 + 1] *= s.y;
vertices[i * 3 + 2] *= s.z;
}
// Modify the normals
if (normals != NULL)
{
// TODO: Make a fast special case for uniform scale factors, where
// renormalization is not required.
Vec3f is(1.0f / s.x, 1.0f / s.y, 1.0f / s.z);
for (i = 0; i < nVertices; i++)
{
int n = i * 3;
Vec3f normal(normals[n] * is.x, normals[n + 1] * is.y, normals[n + 2] * is.z);
normal.normalize();
normals[n] = normal.x;
normals[n + 1] = normal.y;
normals[n + 2] = normal.z;
}
}
}
void SphereMesh::displace(const DisplacementMap& dispmap,
float height)
{
// assert(dispMap.getWidth() == nSlices);
// assert(dispMap.getHeight() == nRings);
for (int i = 0; i < nRings; i++)
{
for (int j = 0; j <= nSlices; j++)
{
int n = (i * (nSlices + 1) + j) * 3;
/*
float theta = (float) j / (float) nSlices * (float) PI * 2;
float x = (float) (cos(phi) * cos(theta));
float y = (float) sin(phi);
float z = (float) (cos(phi) * sin(theta));
*/
Vec3f normal(normals[n], normals[n + 1], normals[n + 2]);
int k = (j == nSlices) ? 0 : j;
Vec3f v = normal * dispmap.getDisplacement(k, i) * height;
vertices[n] += v.x;
vertices[n + 1] += v.y;
vertices[n + 2] += v.z;
}
}
}
void SphereMesh::displace(DisplacementMapFunc func, void* info)
{
for (int i = 0; i < nRings; i++)
{
float v = (float) i / (float) (nRings - 1);
for (int j = 0; j <= nSlices; j++)
{
float u = (float) j / (float) nSlices;
int n = (i * (nSlices + 1) + j) * 3;
Vec3f normal(normals[n], normals[n + 1], normals[n + 2]);
Vec3f vert = normal * func(u, v, info);
vertices[n] += vert.x;
vertices[n + 1] += vert.y;
vertices[n + 2] += vert.z;
}
}
}

51
src/spheremesh.h 100644
View File

@ -0,0 +1,51 @@
// mesh.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _SPHEREMESH_H_
#define _SPHEREMESH_H_
#include "vecmath.h"
#include "mesh.h"
#include "dispmap.h"
class SphereMesh : public Mesh
{
public:
SphereMesh(float radius, int _nRings, int _nSlices);
SphereMesh(Vec3f size, int _nRings, int _nSlices);
SphereMesh(Vec3f size,
const DisplacementMap& dispmap,
float height = 1.0f);
SphereMesh(Vec3f size,
int _nRings, int _nSlices,
DisplacementMapFunc func,
void* info);
~SphereMesh();
void render();
private:
void createSphere(float radius, int nRings, int nSlices);
void generateNormals();
void scale(Vec3f);
void fixNormals();
void displace(const DisplacementMap& dispmap, float height);
void displace(DisplacementMapFunc func, void* info);
int nRings;
int nSlices;
int nVertices;
float* vertices;
float* normals;
float* texCoords;
int nIndices;
unsigned short* indices;
};
#endif // _SPHEREMESH_H_

166
src/star.cpp 100644
View File

@ -0,0 +1,166 @@
// star.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "celestia.h"
#include "astro.h"
#include "mathlib.h"
#include "star.h"
#define SOLAR_TEMPERATURE 5780.0f
#define SOLAR_RADIUS 696000
// Star temperature data from Carroll and Ostlie's
// _Modern Astrophysics_ (1996), p. A-13 - A-18. Temperatures from
// missing (an typically not used) types in those tables were just
// interpolated.
// TODO
// These temperatures are valid for main sequence stars . . . add
// tables for giants and supergiants
static float tempO[10] =
{
50000, 50000, 50000, 50000, 47000,
44500, 41000, 38000, 35800, 33000
};
static float tempB[10] =
{
30000, 25400, 22000, 18700, 17000,
15400, 14000, 13000, 11900, 10500
};
static float tempA[10] =
{
9520, 9230, 8970, 8720, 8460, 8200, 8020, 7850, 7580, 7390
};
static float tempF[10] =
{
7200, 7050, 6890, 6740, 6590, 6440, 6360, 6280, 6200, 6110
};
static float tempG[10] =
{
6030, 5940, 5860, 5830, 5800, 5770, 5700, 5630, 5570, 5410
};
static float tempK[10] =
{
5250, 5080, 4900, 4730, 4590, 4350, 4200, 4060, 3990, 3920
};
static float tempM[10] =
{
3850, 3720, 3580, 3470, 3370, 3240, 3050, 2940, 2640, 2600
};
// Return the radius of the star in kilometers
float Star::getRadius() const
{
// Use the Stefan-Boltzmann law to estimate the radius of a
// star from surface temperature and luminosity
return SOLAR_RADIUS * (float) sqrt(getLuminosity()) /
square(getTemperature() / SOLAR_TEMPERATURE);
}
// Return the temperature in Kelvin
float Star::getTemperature() const
{
if (stellarClass.getStarType() == StellarClass::NormalStar)
{
unsigned int specSubClass = stellarClass.getSpectralSubclass();
switch (stellarClass.getSpectralClass())
{
case StellarClass::Spectral_O:
return tempO[specSubClass];
case StellarClass::Spectral_B:
return tempB[specSubClass];
case StellarClass::Spectral_A:
return tempA[specSubClass];
case StellarClass::Spectral_F:
return tempF[specSubClass];
case StellarClass::Spectral_G:
return tempG[specSubClass];
case StellarClass::Spectral_K:
return tempK[specSubClass];
case StellarClass::Spectral_M:
return tempM[specSubClass];
case StellarClass::Spectral_R:
return tempK[specSubClass];
case StellarClass::Spectral_S:
return tempM[specSubClass];
case StellarClass::Spectral_N:
return tempM[specSubClass];
case StellarClass::Spectral_WC:
return tempM[specSubClass];
case StellarClass::Spectral_WN:
return tempM[specSubClass];
default:
// TODO: Bad spectral class
return -1;
}
}
else if (stellarClass.getStarType() == StellarClass::WhiteDwarf)
{
// TODO
// Return a better temperature estimate for white dwarf
// and neutron stars.
return 10000;
}
else if (stellarClass.getStarType() == StellarClass::NeutronStar)
{
return 10000;
}
else
{
// TODO: Bad star type
return -1;
}
}
void Star::setCatalogNumber(uint32 n)
{
catalogNumber = n;
}
void Star::setPosition(float x, float y, float z)
{
position = Point3f(x, y, z);
}
void Star::setPosition(Point3f p)
{
position = p;
}
void Star::setLuminosity(float lum)
{
luminosity = lum;
}
void Star::setStellarClass(StellarClass sc)
{
stellarClass = sc;
}
float Star::getAbsoluteMagnitude() const
{
return astro::lumToAbsMag(luminosity);
}
void Star::setAbsoluteMagnitude(float mag)
{
luminosity = astro::absMagToLum(mag);
}

79
src/star.h 100644
View File

@ -0,0 +1,79 @@
// star.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _STAR_H_
#define _STAR_H_
#include "celestia.h"
#include "basictypes.h"
#include "vecmath.h"
#include "stellarclass.h"
class Star
{
public:
inline Star();
inline uint32 getCatalogNumber() const;
inline StellarClass getStellarClass() const;
inline Point3f getPosition() const;
inline float getLuminosity() const;
float getRadius() const;
float getTemperature() const;
void setCatalogNumber(uint32);
void setPosition(float, float, float);
void setPosition(Point3f);
void setStellarClass(StellarClass);
void setLuminosity(float);
float getAbsoluteMagnitude() const;
void setAbsoluteMagnitude(float);
enum {
InvalidStar = 0xffffffff
};
private:
uint32 catalogNumber;
Point3f position;
float luminosity; // in units of solar luminosity
StellarClass stellarClass;
};
Star::Star() : catalogNumber(0),
position(0, 0, 0),
luminosity(1),
stellarClass()
{
}
uint32 Star::getCatalogNumber() const
{
return catalogNumber;
}
float Star::getLuminosity() const
{
return luminosity;
}
StellarClass Star::getStellarClass() const
{
return stellarClass;
}
Point3f Star::getPosition() const
{
return position;
}
#endif // _STAR_H_

271
src/starcat.c 100644
View File

@ -0,0 +1,271 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define ID_NONE -1
#define SPECTRAL_O 0
#define SPECTRAL_B 1
#define SPECTRAL_A 2
#define SPECTRAL_F 3
#define SPECTRAL_G 4
#define SPECTRAL_K 5
#define SPECTRAL_M 6
#define SPECTRAL_R 7
#define SPECTRAL_S 8
#define SPECTRAL_N 9
#define LUM_Ia 0
#define LUM_Ib 1
#define LUM_II 2
#define LUM_III 3
#define LUM_IV 4
#define LUM_V 5
typedef struct {
char colorType;
char subType;
char luminosity;
float colorIndex;
} SpectralType;
typedef struct {
int HIP; /* HIPPARCOS catalogue number */
int HD; /* HD catalogue number */
char *commonName;
float appMag; /* Apparent magnitude */
float RA; /* 0 -- 24 hours */
float dec; /* -90 -- +90 degrees */
float parallax; /* in milliarcseconds */
char spectral[13];
} Star;
typedef struct {
int HD;
char *commonName;
char *altName;
} HDNameEnt;
/* Hardcoded file names */
#define HIPPARCOS_MAIN_DB "hip_main.dat"
#define COMMON_NAMES_DB "hdnames.dat"
HDNameEnt *hdNames;
int nHDNames;
Star *Stars;
int nStars;
int CompareHDNameEnt(const void *a, const void *b)
{
int hda = ((HDNameEnt *) a)->HD;
int hdb = ((HDNameEnt *) b)->HD;
if (hda < hdb)
return -1;
else if (hda > hdb)
return 1;
else
return 0;
}
HDNameEnt *ReadCommonNames(FILE *fp)
{
char buf[256];
int i;
hdNames = malloc(sizeof(HDNameEnt) * 3000);
if (hdNames == NULL)
return NULL;
for (i = 0; ; i++) {
char *name1, *name2, len;
if (fgets(buf, 256, fp) == NULL)
break;
/* Strip trailing newline */
len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
name1 = index(buf, ':');
if (name1 == NULL)
break;
name1[0] = '\0';
name1++;
name2 = index(name1, ':');
if (name2 == NULL)
break;
name2[0] = '\0';
name2++;
{
int hd;
if (sscanf(buf, "%d", &hd) != 1)
break;
hdNames[i].HD = hd;
if (name1[0] != '\0') {
hdNames[i].commonName = malloc(strlen(name1) + 1);
strcpy(hdNames[i].commonName, name1);
} else if (name2[0] != '\0') {
hdNames[i].commonName = malloc(strlen(name2) + 1);
strcpy(hdNames[i].commonName, name2);
}
}
}
nHDNames = i;
qsort(hdNames, nHDNames, sizeof(HDNameEnt), CompareHDNameEnt);
#if 0
for (i = 0; i < nHDNames; i++) {
if (hdNames[i].commonName != NULL) {
printf("%6d %s\n", hdNames[i].HD, hdNames[i].commonName);
}
}
#endif
return hdNames;
}
char *LookupName(int HD)
{
HDNameEnt key;
HDNameEnt *found;
key.HD = HD;
found = (HDNameEnt *) bsearch((void *) &key, (void *) hdNames,
nHDNames, sizeof(HDNameEnt),
CompareHDNameEnt);
if (found == NULL)
return NULL;
else
return found->commonName;
}
#define HIPPARCOS_RECORD_LENGTH 512
Star *ReadHipparcosCatalog(FILE *fp)
{
char buf[HIPPARCOS_RECORD_LENGTH];
int i;
int maxStars = 120000;
Star *stars;
int nBright = 0, nGood = 0;
char nameBuf[20];
stars = malloc(maxStars * sizeof(Star));
if (stars == NULL)
return NULL;
for (i = 0; ; i++) {
int hh, mm, deg;
float seconds;
float parallaxError;
char degSign;
if (fgets(buf, HIPPARCOS_RECORD_LENGTH, fp) == NULL)
break;
sscanf(buf + 2, "%d", &stars[i].HIP);
if (sscanf(buf + 390, "%d", &stars[i].HD) != 1)
stars[i].HD = ID_NONE;
sscanf(buf + 41, "%f", &stars[i].appMag);
sscanf(buf + 79, "%f", &stars[i].parallax);
sscanf(buf + 17, "%d %d %f", &hh, &mm, &seconds);
stars[i].RA = hh + (float) mm / 60.0f + (float) seconds / 3600.0f;
sscanf(buf + 29, "%c%d %d %f", &degSign, &deg, &mm, &seconds);
stars[i].dec = deg + (float) mm / 60.0f + (float) seconds / 3600.0f;
if (degSign == '-')
stars[i].dec = -stars[i].dec;
sscanf(buf + 435, "%12s", &stars[i].spectral);
sscanf(buf + 119, "%f", &parallaxError);
if (/* stars[i].appMag < 4.0f */
stars[i].parallax > 0 && 3260 / stars[i].parallax < 20) {
nBright++;
#if 0
if (parallaxError / stars[i].parallax > 0.25f ||
parallaxError / stars[i].parallax < 0.0f) {
#endif
if (1) {
char *name = LookupName(stars[i].HD);
if (name == NULL) {
if (stars[i].HD != ID_NONE) {
sprintf(nameBuf, "HD%d", stars[i].HD);
name = nameBuf;
} else {
sprintf(nameBuf, "HIP%d", stars[i].HIP);
name = nameBuf;
}
}
printf("%-20s %5.2f %6.2f %3d%% %12s %5.2f %5.2f\n",
name,
stars[i].appMag,
3260.0f / stars[i].parallax,
(int) (100.0f * parallaxError / stars[i].parallax),
stars[i].spectral,
stars[i].RA, stars[i].dec);
} else {
nGood++;
}
}
}
nStars = i;
printf("Stars: %d, Bright: %d, Good: %d\n", nStars, nBright, nGood);
return stars;
}
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(COMMON_NAMES_DB, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening %s\n", COMMON_NAMES_DB);
return 1;
}
hdNames = ReadCommonNames(fp);
fclose(fp);
fp = NULL;
if (hdNames == NULL) {
fprintf(stderr, "Error reading names file.\n");
return 1;
}
fp = fopen(HIPPARCOS_MAIN_DB, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening %s\n", HIPPARCOS_MAIN_DB);
return 1;
}
Stars = ReadHipparcosCatalog(fp);
fclose(fp);
if (Stars == NULL) {
fprintf(stderr, "Error reading HIPPARCOS database.");
return 1;
}
#if 0
{
int i;
for (i = 0; i < nStars; i++) {
if (Stars[i].spectral[0] == 'O') {
char *name = LookupName(Stars[i].HD);
if (name != NULL)
printf("%s ", name);
printf("%6d %6.3f %6.3f %s\n",
Stars[i].HD, Stars[i].RA, Stars[i].dec, Stars[i].spectral);
}
}
}
#endif
printf("Stars in catalog = %d\n", nStars);
}

354
src/stardb.cpp 100644
View File

@ -0,0 +1,354 @@
// stardb.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include "celestia.h"
#include "mathlib.h"
#include "stardb.h"
using namespace std;
#define MAX_STARS 120000
static string HDCatalogPrefix("HD ");
static string HIPPARCOSCatalogPrefix("HIP ");
static string GlieseCatalogPrefix("Gliese ");
static string RossCatalogPrefix("Ross ");
static string LacailleCatalogPrefix("Lacaille ");
StarDatabase::StarDatabase() : nStars(0), stars(NULL), names(NULL)
{
}
StarDatabase::~StarDatabase()
{
if (stars != NULL)
delete [] stars;
}
// Less than operator for stars is used to sort and find stars by catalog
// number
bool operator<(Star& a, Star& b)
{
return a.getCatalogNumber() < b.getCatalogNumber();
}
bool operator<(Star& s, uint32 n)
{
return s.getCatalogNumber() < n;
}
Star* StarDatabase::find(uint32 catalogNumber) const
{
Star* star = lower_bound(stars, stars + nStars, catalogNumber);
if (star != stars + nStars && star->getCatalogNumber() == catalogNumber)
return star;
else
return NULL;
}
Star* StarDatabase::find(string name) const
{
if (name.compare(0, HDCatalogPrefix.length(), HDCatalogPrefix) == 0)
{
// Search by catalog number
uint32 catalogNumber = (uint32) atoi(string(name, HDCatalogPrefix.length(),
string::npos).c_str());
return find(catalogNumber);
}
else if (name.compare(0, HIPPARCOSCatalogPrefix.length(), HIPPARCOSCatalogPrefix) == 0)
{
uint32 catalogNumber = (uint32) atoi(string(name, HIPPARCOSCatalogPrefix.length(), string::npos).c_str()) | 0x10000000;
return find(catalogNumber);
}
else
{
string conAbbrev;
string designation;
if (name.length() > 3)
{
conAbbrev = string(name, name.length() - 3, 3);
designation = string(name, 0, name.length() - 4);
}
// Search the list of star proper names and designations
for (StarNameDatabase::const_iterator iter = names->begin();
iter != names->end(); iter++)
{
if (iter->second->getName() == name)
{
return find(iter->first);
}
else
{
Constellation* con = iter->second->getConstellation();
if (con != NULL)
{
if (con->getAbbreviation() == conAbbrev &&
iter->second->getDesignation() == designation)
{
return find(iter->first);
}
}
}
}
return NULL;
}
}
// Return the name for the star with specified catalog number. The returned string
// will be:
// the common name if it exists, otherwise
// the Bayer or Flamsteed designation if it exists, otherwise
// the HD catalog number if it exists, otherwise
// the HIPPARCOS catalog number.
string StarDatabase::getStarName(uint32 catalogNumber) const
{
StarNameDatabase::iterator iter = names->find(catalogNumber);
if (iter != names->end())
{
StarName* starName = iter->second;
if (starName->getName() != "")
return starName->getName();
Constellation* constellation = starName->getConstellation();
if (constellation != NULL)
{
string name = starName->getDesignation();
name += ' ';
name += constellation->getGenitive();
return name;
}
//return starName->getDesignation + " " + constellation->getGenitive();
}
return "";
#if 0
if ((star.getCatalogNumber() & 0xf0000000) == 0)
console << "HD " << star.getCatalogNumber() << '\n';
else
console << "HIP " << (star.getCatalogNumber() & 0x0fffffff) << '\n';
#endif
}
StarNameDatabase* StarDatabase::getNameDatabase() const
{
return names;
}
void StarDatabase::setNameDatabase(StarNameDatabase* _names)
{
names = _names;
}
StarDatabase *StarDatabase::read(istream& in)
{
StarDatabase *db = new StarDatabase();
if (db == NULL)
return NULL;
uint32 nStars = 0;
in.read((char *) &nStars, sizeof nStars);
if (!in.good())
{
delete db;
return NULL;
};
db->stars = new Star[nStars];
if (db->stars == NULL)
{
delete db;
return NULL;
}
uint32 throwOut = 0;
uint32 fixUp = 0;
while (db->nStars < MAX_STARS)
{
uint32 catNo = 0;
float RA = 0, dec = 0, parallax = 0;
int16 appMag;
uint16 stellarClass;
uint8 parallaxError;
in.read((char *) &catNo, sizeof catNo);
in.read((char *) &RA, sizeof RA);
in.read((char *) &dec, sizeof dec);
in.read((char *) &parallax, sizeof parallax);
in.read((char *) &appMag, sizeof appMag);
in.read((char *) &stellarClass, sizeof stellarClass);
in.read((char *) &parallaxError, sizeof parallaxError);
if (!in.good())
break;
Star *star = &db->stars[db->nStars];
// Compute distance based on parallax
double distance = 3.26 / (parallax > 0.0 ? parallax / 1000.0 : 1e-6);
// Convert from RA, dec spherical to cartesian coordinates
double theta = RA / 24.0 * PI * 2;
// double phi = (1.0 - dec / 90.0) * PI / 2;
double phi = (dec / 90.0 - 1.0) * PI / 2;
double x = -cos(theta) * sin(phi) * distance;
double y = -cos(phi) * distance;
double z = -sin(theta) * sin(phi) * distance;
star->setPosition((float) x, (float) y, (float) z);
// Use apparent magnitude and distance to determine the absolute
// magnitude of the star.
star->setAbsoluteMagnitude((float) (appMag / 256.0 + 5 -
5 * log10(distance / 3.26)));
StellarClass sc((StellarClass::StarType) (stellarClass >> 12),
(StellarClass::SpectralClass)(stellarClass >> 8 & 0xf),
(unsigned int) (stellarClass >> 4 & 0xf),
(StellarClass::LuminosityClass) (stellarClass & 0xf));
star->setStellarClass(sc);
star->setCatalogNumber(catNo);
// Use a photometric estimate of distance if parallaxError is
// greater than 25%.
if (parallaxError > 50)
{
if (appMag / 256.0 > 6)
throwOut++;
else
fixUp++;
}
db->nStars++;
}
if (in.bad())
{
delete db;
db = NULL;
}
sort(db->stars, db->stars + db->nStars);
cout << "nStars = " << db->nStars << '\n';
cout << "throw out = " << throwOut << '\n';
cout << "fix up = " << fixUp << '\n';
return db;
}
StarNameDatabase* StarDatabase::readNames(istream& in)
{
StarNameDatabase* db = new StarNameDatabase();
bool failed = false;
string s;
for (;;)
{
unsigned int catalogNumber;
char sep;
in >> catalogNumber;
if (in.eof())
break;
if (in.bad())
{
failed = true;
break;
}
in >> sep;
if (sep != ':')
{
failed = true;
break;
}
// Get the rest of the line
getline(in, s);
unsigned int nextSep = s.find_first_of(':');
if (nextSep == string::npos)
{
failed = true;
break;
}
string common, designation;
string conAbbr;
string conName;
string bayerLetter;
if (nextSep != 0)
common = s.substr(0, nextSep);
designation = s.substr(nextSep + 1, string::npos);
if (designation != "")
{
nextSep = designation.find_last_of(' ');
if (nextSep != string::npos)
{
bayerLetter = designation.substr(0, nextSep);
conAbbr = designation.substr(nextSep + 1, string::npos);
}
}
Constellation *constel;
if (designation != "")
{
for (int i = 0; i < 88; i++)
{
constel = Constellation::getConstellation(i);
if (constel == NULL)
{
DPRINTF("Error getting constellation %d", i);
break;
}
if (constel->getAbbreviation() == conAbbr)
{
conName = constel->getName();
break;
}
}
}
else
{
constel = NULL;
}
StarName* sn = new StarName(common, bayerLetter, constel);
db->insert(StarNameDatabase::value_type(catalogNumber, sn));
}
if (failed)
{
delete db;
db = NULL;
}
return db;
}

65
src/stardb.h 100644
View File

@ -0,0 +1,65 @@
// stardb.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _STARDB_H_
#define _STARDB_H_
#include <iostream>
#include <map>
#include "constellation.h"
#include "starname.h"
#include "star.h"
typedef std::map<uint32, StarName*> StarNameDatabase;
class StarDatabase
{
public:
static StarDatabase* read(std::istream&);
static StarNameDatabase* readNames(std::istream&);
StarDatabase();
~StarDatabase();
inline Star* getStar(uint32) const;
inline uint32 size() const;
Star* find(uint32 catalogNumber) const;
Star* find(std::string) const;
string getStarName(uint32 catalogNumber) const;
StarNameDatabase* getNameDatabase() const;
void setNameDatabase(StarNameDatabase*);
private:
int nStars;
Star *stars;
StarNameDatabase* names;
};
Star* StarDatabase::getStar(uint32 n) const
{
return stars + n;
}
uint32 StarDatabase::size() const
{
return nStars;
}
#if 0
bool GetCatalogNumber(std::string name,
const StarNameDatabase& namedb,
uint32& catalogNumber);
#endif
#endif // _STARDB_H_

63
src/starname.cpp 100644
View File

@ -0,0 +1,63 @@
// starname.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "celestia.h"
#include "starname.h"
static char *greekAlphabet[] =
{
"Alpha",
"Beta",
"Gamma",
"Delta",
"Epsilon",
"Zeta",
"Eta",
"Theta",
"Iota",
"Kappa",
"Lambda",
"Mu",
"Nu",
"Xi",
"Omicron",
"Pi",
"Rho",
"Sigma",
"Tau",
"Upsilon",
"Phi",
"Chi",
"Psi",
"Omega"
};
StarName::StarName(string _name, string _designation, Constellation *_constel)
{
name = _name;
designation = _designation;
constellation = _constel;
}
string StarName::getName()
{
return name;
}
string StarName::getDesignation()
{
return designation;
}
Constellation *StarName::getConstellation()
{
return constellation;
}

32
src/starname.h 100644
View File

@ -0,0 +1,32 @@
// starname.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _STARNAME_H_
#define _STARNAME_H_
#include <string>
#include "basictypes.h"
#include "constellation.h"
using std::string;
class StarName
{
public:
StarName(string _name, string _designation, Constellation *_constel);
string getName();
string getDesignation(); // get Bayer or Flamsteed designation
Constellation *getConstellation();
private:
string name;
string designation; // Bayer or Flamsteed designation
Constellation *constellation;
};
#endif // _STARNAME_H_

138
src/startest.cpp 100644
View File

@ -0,0 +1,138 @@
// startest.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <math.h>
#include "celestia.h"
#include "stardb.h"
#include "visstars.h"
#include "mathlib.h"
int main(int argc, char *argv[])
{
if (argc != 3)
{
cerr << "usage: " << argv[0] << " <stars file> <star names file>\n";
exit(1);
}
ifstream starFile(argv[1], ios::in | ios::binary);
if (!starFile.good())
{
cerr << "Error opening " << argv[1] << '\n';
exit(1);
}
ifstream starNamesFile(argv[2], ios::in);
if (!starNamesFile.good())
{
cerr << "Error opening " << argv[2] << '\n';
exit(1);
}
StarDatabase* starDB = StarDatabase::read(starFile);
if (starDB == NULL)
{
cerr << "Error reading stars file\n";
exit(1);
}
StarNameDatabase* starNameDB = StarDatabase::readNames(starNamesFile);
if (starNameDB == NULL)
{
cerr << "Error reading star names file\n";
exit(1);
}
cout << "nNames = " << starNameDB->size() << '\n';
#if 0
for (;;)
{
int hd;
if (!(cin >> hd))
break;
StarNameDatabase::iterator iter = starNameDB->find(hd);
if (iter == starNameDB->end())
{
cout << "No name found.\n";
}
else
{
cout << iter->second->getName() << '\n';
}
if (!cin.good())
break;
}
#endif
uint d10 = 0, d20 = 0, d30 = 0, bright = 0;
uint subdwarves = 0;
for (uint32 i = 0; i < starDB->size(); i++)
{
Star *star = starDB->getStar(i);
Point3f pos = star->getPosition();
float distance = (float) sqrt(pos.x * pos.x + pos.y * pos.y +
pos.z * pos.z);
float appMag = star->getAbsoluteMagnitude() - 5 + 5 *
(float) log10(distance / 3.26);
if (appMag < 6)
bright++;
if (star->getStellarClass().getLuminosityClass() == StellarClass::Lum_VI)
subdwarves++;
if (distance < 30)
{
d30++;
if (distance < 20)
{
uint32 catNo = star->getCatalogNumber();
StarNameDatabase::iterator iter = starNameDB->find(catNo);
if (iter != starNameDB->end())
{
cout << iter->second->getName() << " : " << distance << " : " << star->getStellarClass() << " : " << star->getLuminosity() << '\n';
}
else
{
cout << catNo << " : " << distance << " : " << star->getStellarClass() << " : " << star->getLuminosity() << '\n';
}
d20++;
if (distance < 10)
{
d10++;
}
}
}
}
cout << "subdwarves (Type VI):" << subdwarves << '\n';
cout << "mag < 6.0: " << bright << '\n';
cout << "closer than 10 ly: " << d10 << '\n';
cout << "closer than 20 ly: " << d20 << '\n';
cout << "closer than 30 ly: " << d30 << '\n';
{
Observer obs;
VisibleStarSet visset(starDB);
visset.setCloseDistance(20);
visset.setLimitingMagnitude(5.5f);
visset.updateAll(obs);
vector<uint32> *starvec = visset.getVisibleSet();
cout << "visible: " << starvec->size() << "\n";
}
return 0;
}

View File

@ -0,0 +1,93 @@
// stellarclass.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "celestia.h"
#include "stellarclass.h"
using namespace std;
Color StellarClass::getApparentColor() const
{
switch (getSpectralClass())
{
case Spectral_O:
return Color(0.7f, 0.8f, 1.0f);
case Spectral_B:
return Color(0.8f, 0.9f, 1.0f);
case Spectral_A:
return Color(1.0f, 1.0f, 1.0f);
case Spectral_F:
return Color(1.0f, 1.0f, 0.88f);
case Spectral_G:
return Color(1.0f, 1.0f, 0.75f);
case StellarClass::Spectral_K:
return Color(1.0f, 0.9f, 0.7f);
case StellarClass::Spectral_M:
return Color(1.0f, 0.7f, 0.7f);
case StellarClass::Spectral_R:
case StellarClass::Spectral_S:
case StellarClass::Spectral_N:
return Color(1.0f, 0.6f, 0.6f);
default:
// TODO: Figure out reasonable colors for Wolf-Rayet stars,
// white dwarfs, and other oddities
return Color(1.0f, 1.0f, 1.0f);
}
}
ostream& operator<<(ostream& s, const StellarClass& sc)
{
StellarClass::StarType st = sc.getStarType();
if (st == StellarClass::WhiteDwarf)
{
s << 'D';
}
else if (st == StellarClass::NeutronStar)
{
s << 'Q';
}
else if (st == StellarClass::NormalStar)
{
s << "OBAFGKMRSNWW"[(unsigned int) sc.getSpectralClass()];
s << "0123456789"[sc.getSpectralSubclass()];
s << ' ';
switch (sc.getLuminosityClass())
{
case StellarClass::Lum_Ia0:
s << "I-a0";
break;
case StellarClass::Lum_Ia:
s << "I-a";
break;
case StellarClass::Lum_Ib:
s << "I-b";
break;
case StellarClass::Lum_II:
s << "II";
break;
case StellarClass::Lum_III:
s << "III";
break;
case StellarClass::Lum_IV:
s << "IV";
break;
case StellarClass::Lum_V:
s << "V";
break;
case StellarClass::Lum_VI:
s << "VI";
break;
}
}
return s;
}

115
src/stellarclass.h 100644
View File

@ -0,0 +1,115 @@
// stellarclass.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _STELLARCLASS_H_
#define _STELLARCLASS_H_
#include <iostream>
#include "basictypes.h"
#include "color.h"
class StellarClass
{
public:
enum StarType
{
NormalStar = 0,
WhiteDwarf = 1,
NeutronStar = 2,
};
enum SpectralClass
{
Spectral_O = 0,
Spectral_B = 1,
Spectral_A = 2,
Spectral_F = 3,
Spectral_G = 4,
Spectral_K = 5,
Spectral_M = 6,
Spectral_R = 7,
Spectral_S = 8,
Spectral_N = 9,
Spectral_WC = 10,
Spectral_WN = 11,
};
enum LuminosityClass
{
Lum_Ia0 = 0,
Lum_Ia = 1,
Lum_Ib = 2,
Lum_II = 3,
Lum_III = 4,
Lum_IV = 5,
Lum_V = 6,
Lum_VI = 7,
};
inline StellarClass();
inline StellarClass(StarType,
SpectralClass,
unsigned int,
LuminosityClass);
inline StarType getStarType() const;
inline SpectralClass getSpectralClass() const;
inline unsigned int getSpectralSubclass() const;
inline LuminosityClass getLuminosityClass() const;
Color getApparentColor() const;
private:
// It'd be nice to use bitfields, but gcc can't seem to pack
// them into under 4 bytes.
uint16 data;
};
std::ostream& operator<<(std::ostream& s, const StellarClass& sc);
StellarClass::StellarClass(StarType t,
SpectralClass sc,
unsigned int ssub,
LuminosityClass lum)
{
data = (((unsigned short) t << 12) |
((unsigned short) sc << 8) |
((unsigned short) ssub << 4) |
((unsigned short) lum));
}
StellarClass::StellarClass()
{
data = 0;
}
StellarClass::StarType StellarClass::getStarType() const
{
return (StarType) (data >> 12);
}
StellarClass::SpectralClass StellarClass::getSpectralClass() const
{
return (SpectralClass) (data >> 8 & 0xf);
}
unsigned int StellarClass::getSpectralSubclass() const
{
return data >> 4 & 0xf;
}
StellarClass::LuminosityClass StellarClass::getLuminosityClass() const
{
return (LuminosityClass) (data & 0xf);
}
#endif // _STELLARCLASS_H_

527
src/texfont.cpp 100644
View File

@ -0,0 +1,527 @@
/* Copyright (c) Mark J. Kilgard, 1997. */
/* 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)
#pragma warning (disable:4244) /* disable bogus conversion warnings */
#endif
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include <GL/glu.h>
#include "texfont.h"
using namespace std;
#if 0
/* Uncomment to debug various scenarios. */
#undef GL_VERSION_1_1
#undef GL_EXT_texture_object
#undef GL_EXT_texture
#endif
#ifndef GL_VERSION_1_1
# if defined(GL_EXT_texture_object)
# define glGenTextures glGenTexturesEXT
# define glBindTexture glBindTextureEXT
# else
/* Without OpenGL 1.1 or the texture object extension, use display lists. */
# define USE_DISPLAY_LISTS
# endif
# if defined(GL_EXT_texture)
# define GL_INTENSITY4 GL_INTENSITY4_EXT
int useLuminanceAlpha = 0;
# else
/* Intensity texture format not in OpenGL 1.0; added by the EXT_texture
extension and now part of OpenGL 1.1. */
int useLuminanceAlpha = 1;
# endif
#else
/* OpenGL 1.1 case. */
int useLuminanceAlpha = 0;
#endif
static TexGlyphVertexInfo NullGlyph = {
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
0
};
/* byte swap a 32-bit value */
#define SWAPL(x, n) { \
n = ((char *) (x))[0];\
((char *) (x))[0] = ((char *) (x))[3];\
((char *) (x))[3] = n;\
n = ((char *) (x))[1];\
((char *) (x))[1] = ((char *) (x))[2];\
((char *) (x))[2] = n; }
/* byte swap a short */
#define SWAPS(x, n) { \
n = ((char *) (x))[0];\
((char *) (x))[0] = ((char *) (x))[1];\
((char *) (x))[1] = n; }
static TexGlyphVertexInfo *getTCVI(TexFont * txf, int c)
{
TexGlyphVertexInfo *tgvi;
/* Automatically substitute uppercase letters with lowercase if not
uppercase available (and vice versa). */
if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
tgvi = txf->lut[c - txf->min_glyph];
if (tgvi) {
return tgvi;
}
if (islower(c)) {
c = toupper(c);
if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
return txf->lut[c - txf->min_glyph];
}
}
if (isupper(c)) {
c = tolower(c);
if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
return txf->lut[c - txf->min_glyph];
}
}
}
return &NullGlyph;
#if 0
fprintf(stderr,
"texfont: tried to access unavailable font character \"%c\" (%d)\n",
isprint(c) ? c : ' ', c);
abort();
/* NOTREACHED */
#endif
}
static char *lastError;
char *txfErrorString(void)
{
return lastError;
}
TexFont *txfLoadFont(char *filename)
{
TexFont *txf;
FILE *file;
GLfloat w, h, xstep, ystep;
char fileid[4], tmp;
unsigned char *texbitmap;
int min_glyph, max_glyph;
int endianness, swap, format, stride, width, height;
int i, j;
unsigned long got;
txf = NULL;
file = fopen(filename, "rb");
if (file == NULL) {
lastError = "file open failed.";
goto error;
}
txf = (TexFont *) malloc(sizeof(TexFont));
if (txf == NULL) {
lastError = "out of memory.";
goto error;
}
/* For easy cleanup in error case. */
txf->tgi = NULL;
txf->tgvi = NULL;
txf->lut = NULL;
txf->teximage = NULL;
got = fread(fileid, 1, 4, file);
if (got != 4 || strncmp(fileid, "\377txf", 4)) {
lastError = "not a texture font file.";
goto error;
}
/*CONSTANTCONDITION*/ assert(sizeof(int) == 4); /* Ensure external file format size. */
got = fread(&endianness, sizeof(int), 1, file);
if (got == 1 && endianness == 0x12345678) {
swap = 0;
} else if (got == 1 && endianness == 0x78563412) {
swap = 1;
} else {
lastError = "not a texture font file.";
goto error;
}
#define EXPECT(n) if (got != (unsigned long) n) { lastError = "premature end of file."; goto error; }
got = fread(&format, sizeof(int), 1, file);
EXPECT(1);
got = fread(&txf->tex_width, sizeof(int), 1, file);
EXPECT(1);
got = fread(&txf->tex_height, sizeof(int), 1, file);
EXPECT(1);
got = fread(&txf->max_ascent, sizeof(int), 1, file);
EXPECT(1);
got = fread(&txf->max_descent, sizeof(int), 1, file);
EXPECT(1);
got = fread(&txf->num_glyphs, sizeof(int), 1, file);
EXPECT(1);
if (swap) {
SWAPL(&format, tmp);
SWAPL(&txf->tex_width, tmp);
SWAPL(&txf->tex_height, tmp);
SWAPL(&txf->max_ascent, tmp);
SWAPL(&txf->max_descent, tmp);
SWAPL(&txf->num_glyphs, tmp);
}
txf->tgi =
(TexGlyphInfo *) malloc(txf->num_glyphs * sizeof(TexGlyphInfo));
if (txf->tgi == NULL) {
lastError = "out of memory.";
goto error;
}
/*CONSTANTCONDITION*/ assert(sizeof(TexGlyphInfo) == 12); /* Ensure external file format size. */
got = fread(txf->tgi, sizeof(TexGlyphInfo), txf->num_glyphs, file);
EXPECT(txf->num_glyphs);
if (swap) {
for (i = 0; i < txf->num_glyphs; i++) {
SWAPS(&txf->tgi[i].c, tmp);
SWAPS(&txf->tgi[i].x, tmp);
SWAPS(&txf->tgi[i].y, tmp);
}
}
txf->tgvi = (TexGlyphVertexInfo *)
malloc(txf->num_glyphs * sizeof(TexGlyphVertexInfo));
if (txf->tgvi == NULL) {
lastError = "out of memory.";
goto error;
}
w = txf->tex_width;
h = txf->tex_height;
xstep = 0.5 / w;
ystep = 0.5 / h;
txf->max_width = -1; // Celestia addition
for (i = 0; i < txf->num_glyphs; i++) {
TexGlyphInfo *tgi;
tgi = &txf->tgi[i];
txf->tgvi[i].t0[0] = tgi->x / w + xstep;
txf->tgvi[i].t0[1] = tgi->y / h + ystep;
txf->tgvi[i].v0[0] = tgi->xoffset;
txf->tgvi[i].v0[1] = tgi->yoffset;
txf->tgvi[i].t1[0] = (tgi->x + tgi->width) / w + xstep;
txf->tgvi[i].t1[1] = tgi->y / h + ystep;
txf->tgvi[i].v1[0] = tgi->xoffset + tgi->width;
txf->tgvi[i].v1[1] = tgi->yoffset;
txf->tgvi[i].t2[0] = (tgi->x + tgi->width) / w + xstep;
txf->tgvi[i].t2[1] = (tgi->y + tgi->height) / h + ystep;
txf->tgvi[i].v2[0] = tgi->xoffset + tgi->width;
txf->tgvi[i].v2[1] = tgi->yoffset + tgi->height;
txf->tgvi[i].t3[0] = tgi->x / w + xstep;
txf->tgvi[i].t3[1] = (tgi->y + tgi->height) / h + ystep;
txf->tgvi[i].v3[0] = tgi->xoffset;
txf->tgvi[i].v3[1] = tgi->yoffset + tgi->height;
txf->tgvi[i].advance = tgi->advance;
if (tgi->width > txf->max_width)
txf->max_width = tgi->width; // Celestia addition
}
min_glyph = txf->tgi[0].c;
max_glyph = txf->tgi[0].c;
for (i = 1; i < txf->num_glyphs; i++) {
if (txf->tgi[i].c < min_glyph) {
min_glyph = txf->tgi[i].c;
}
if (txf->tgi[i].c > max_glyph) {
max_glyph = txf->tgi[i].c;
}
}
txf->min_glyph = min_glyph;
txf->range = max_glyph - min_glyph + 1;
txf->lut = (TexGlyphVertexInfo **)
calloc(txf->range, sizeof(TexGlyphVertexInfo *));
if (txf->lut == NULL) {
lastError = "out of memory.";
goto error;
}
for (i = 0; i < txf->num_glyphs; i++) {
txf->lut[txf->tgi[i].c - txf->min_glyph] = &txf->tgvi[i];
}
switch (format) {
case TXF_FORMAT_BYTE:
if (useLuminanceAlpha) {
unsigned char *orig;
orig =
(unsigned char *) malloc(txf->tex_width * txf->tex_height);
if (orig == NULL) {
lastError = "out of memory.";
goto error;
}
got = fread(orig, 1, txf->tex_width * txf->tex_height, file);
EXPECT(txf->tex_width * txf->tex_height);
txf->teximage = (unsigned char *)
malloc(2 * txf->tex_width * txf->tex_height);
if (txf->teximage == NULL) {
lastError = "out of memory.";
goto error;
}
for (i = 0; i < txf->tex_width * txf->tex_height; i++) {
txf->teximage[i * 2] = orig[i];
txf->teximage[i * 2 + 1] = orig[i];
}
free(orig);
} else {
txf->teximage = (unsigned char *)
malloc(txf->tex_width * txf->tex_height);
if (txf->teximage == NULL) {
lastError = "out of memory.";
goto error;
}
got =
fread(txf->teximage, 1, txf->tex_width * txf->tex_height,
file);
EXPECT(txf->tex_width * txf->tex_height);
}
break;
case TXF_FORMAT_BITMAP:
width = txf->tex_width;
height = txf->tex_height;
stride = (width + 7) >> 3;
texbitmap = (unsigned char *) malloc(stride * height);
if (texbitmap == NULL) {
lastError = "out of memory.";
goto error;
}
got = fread(texbitmap, 1, stride * height, file);
EXPECT(stride * height);
if (useLuminanceAlpha) {
txf->teximage =
(unsigned char *) calloc(width * height * 2, 1);
if (txf->teximage == NULL) {
lastError = "out of memory.";
goto error;
}
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
txf->teximage[(i * width + j) * 2] = 255;
txf->teximage[(i * width + j) * 2 + 1] = 255;
}
}
}
} else {
txf->teximage = (unsigned char *) calloc(width * height, 1);
if (txf->teximage == NULL) {
lastError = "out of memory.";
goto error;
}
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
txf->teximage[i * width + j] = 255;
}
}
}
}
free(texbitmap);
break;
}
fclose(file);
return txf;
error:
if (txf) {
if (txf->tgi)
free(txf->tgi);
if (txf->tgvi)
free(txf->tgvi);
if (txf->lut)
free(txf->lut);
if (txf->teximage)
free(txf->teximage);
free(txf);
}
if (file)
fclose(file);
return NULL;
}
GLuint
txfEstablishTexture(TexFont * txf, GLuint texobj, GLboolean setupMipmaps)
{
if (txf->texobj == 0) {
if (texobj == 0) {
#if !defined(USE_DISPLAY_LISTS)
glGenTextures(1, &txf->texobj);
#else
txf->texobj = glGenLists(1);
#endif
} else {
txf->texobj = texobj;
}
}
#if !defined(USE_DISPLAY_LISTS)
glBindTexture(GL_TEXTURE_2D, txf->texobj);
#else
glNewList(txf->texobj, GL_COMPILE);
#endif
if (useLuminanceAlpha) {
if (setupMipmaps) {
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA,
txf->tex_width, txf->tex_height,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
txf->teximage);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
txf->tex_width, txf->tex_height, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
txf->teximage);
}
} else {
#if defined(GL_VERSION_1_1) || defined(GL_EXT_texture)
/* Use GL_INTENSITY4 as internal texture format since we want to use as
little texture memory as possible. */
if (setupMipmaps) {
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_INTENSITY4,
txf->tex_width, txf->tex_height,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
txf->teximage);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
txf->tex_width, txf->tex_height, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
}
#else
abort(); /* Should not get here without EXT_texture or OpenGL
1.1. */
#endif
}
#if defined(USE_DISPLAY_LISTS)
glEndList();
glCallList(txf->texobj);
#endif
return txf->texobj;
}
void txfBindFontTexture(TexFont * txf)
{
#if !defined(USE_DISPLAY_LISTS)
glBindTexture(GL_TEXTURE_2D, txf->texobj);
#else
glCallList(txf->texobj);
#endif
}
void txfUnloadFont(TexFont * txf)
{
if (txf->teximage) {
free(txf->teximage);
}
free(txf->tgi);
free(txf->tgvi);
free(txf->lut);
free(txf);
}
void
txfGetStringMetrics(TexFont* txf,
char* s, int len,
int& width, int& maxAscent, int& maxDescent)
{
TexGlyphVertexInfo *tgvi;
int w = 0;
for (int i = 0; i < len; i++)
{
tgvi = getTCVI(txf, s[i]);
w += (int) tgvi->advance;
}
width = w;
maxAscent = txf->max_ascent;
maxDescent = txf->max_descent;
}
void
txfGetStringMetrics(TexFont* txf,
string s,
int& width, int& maxAscent, int& maxDescent)
{
TexGlyphVertexInfo *tgvi;
int w = 0;
for (int i = 0; i < s.length(); i++)
{
tgvi = getTCVI(txf, s[i]);
w += (int) tgvi->advance;
}
width = w;
maxAscent = txf->max_ascent;
maxDescent = txf->max_descent;
}
void txfRenderGlyph(TexFont * txf, int c)
{
TexGlyphVertexInfo *tgvi;
float dx = 0.5f / (float) txf->tex_width;
float dy = 0.5f / (float) txf->tex_height;
tgvi = getTCVI(txf, c);
glBegin(GL_QUADS);
glTexCoord2fv(tgvi->t0);
// glVertex2sv(tgvi->v0);
glVertex2f(tgvi->v0[0], tgvi->v0[1] - 0.1f);
glTexCoord2fv(tgvi->t1);
// glVertex2sv(tgvi->v1);
glVertex2f(tgvi->v1[0], tgvi->v1[1] - 0.1f);
glTexCoord2fv(tgvi->t2);
glVertex2sv(tgvi->v2);
glTexCoord2fv(tgvi->t3);
glVertex2sv(tgvi->v3);
glEnd();
glTranslatef(tgvi->advance, 0.0, 0.0);
}
void txfRenderString(TexFont * txf, char *s, int len)
{
for (int i = 0; i < len; i++)
txfRenderGlyph(txf, s[i]);
}
void txfRenderString(TexFont * txf, string s)
{
for (int i = 0; i < s.length(); i++)
txfRenderGlyph(txf, s[i]);
}
int txfInFont(TexFont * txf, int c)
{
/* NOTE: No uppercase/lowercase substituion. */
if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
if (txf->lut[c - txf->min_glyph]) {
return 1;
}
}
return 0;
}

82
src/texfont.h 100644
View File

@ -0,0 +1,82 @@
/* Copyright (c) Mark J. Kilgard, 1997. */
/* 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. */
#ifndef __TEXFONT_H__
#define __TEXFONT_H__
#include <GL/gl.h>
#include <string>
#define TXF_FORMAT_BYTE 0
#define TXF_FORMAT_BITMAP 1
typedef struct
{
unsigned short c; /* Potentially support 16-bit glyphs. */
unsigned char width;
unsigned char height;
signed char xoffset;
signed char yoffset;
signed char advance;
char dummy; /* Space holder for alignment reasons. */
short x;
short y;
} TexGlyphInfo;
typedef struct {
GLfloat t0[2];
GLshort v0[2];
GLfloat t1[2];
GLshort v1[2];
GLfloat t2[2];
GLshort v2[2];
GLfloat t3[2];
GLshort v3[2];
GLfloat advance;
} TexGlyphVertexInfo;
typedef struct {
GLuint texobj;
int tex_width;
int tex_height;
int max_ascent;
int max_descent;
int max_width; // Celestia addition
int num_glyphs;
int min_glyph;
int range;
unsigned char *teximage;
TexGlyphInfo *tgi;
TexGlyphVertexInfo *tgvi;
TexGlyphVertexInfo **lut;
} TexFont;
extern char *txfErrorString(void);
extern TexFont *txfLoadFont(char *filename);
extern void txfUnloadFont(TexFont * txf);
extern GLuint txfEstablishTexture(TexFont * txf,
GLuint texobj, GLboolean setupMipmaps);
extern void txfBindFontTexture(TexFont * txf);
extern void txfGetStringMetrics(TexFont * txf,
char* s,
int len,
int& width, int& max_ascent, int& max_descent);
extern void txfGetStringMetrics(TexFont* txf,
std::string s,
int& width, int& max_ascent, int& max_descent);
extern void txfRenderGlyph(TexFont* txf, int c);
extern void txfRenderString(TexFont* txf, char* s, int len);
extern void txfRenderString(TexFont* txf, std::string s);
#endif // __TEXFONT_H__

34
src/texmanager.cpp 100644
View File

@ -0,0 +1,34 @@
// texmanager.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "texmanager.h"
TextureManager::~TextureManager()
{
// TODO: Clean up
}
bool TextureManager::find(string name, CTexture** tex)
{
return findResource(name, (void**) tex);
}
CTexture* TextureManager::load(string name)
{
CTexture* tex = LoadTextureFromFile(baseDir + "\\" + name);
if (tex != NULL)
tex->bindName();
addResource(name, (void*) tex);
return tex;
}

32
src/texmanager.h 100644
View File

@ -0,0 +1,32 @@
// texmanager.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _TEXMANAGER_H_
#define _TEXMANAGER_H_
#include <string>
#include <map>
#include "resmanager.h"
#include "texture.h"
class TextureManager : public ResourceManager
{
public:
TextureManager() : ResourceManager() {};
TextureManager(string _baseDir) : ResourceManager(_baseDir) {};
TextureManager(char* _baseDir) : ResourceManager(_baseDir) {};
~TextureManager();
bool find(string name, CTexture**);
CTexture* load(string name);
};
#endif // _TEXMANAGER_H_

442
src/texture.cpp 100644
View File

@ -0,0 +1,442 @@
// texture.cpp
//
// Copyright (C) 2001, Chris Laurel
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#define JPEG_SUPPORT
#include <fstream>
#include "gl.h"
#ifdef JPEG_SUPPORT
#include "ijl.h"
#endif
#include "texture.h"
using namespace std;
typedef struct
{
unsigned char b;
unsigned char m;
unsigned int size;
unsigned int reserved;
unsigned int offset;
} BMPFileHeader;
typedef struct
{
unsigned int size;
int width;
int height;
unsigned short planes;
unsigned short bpp;
unsigned int compression;
unsigned int imageSize;
int widthPPM;
int heightPPM;
unsigned int colorsUsed;
unsigned int colorsImportant;
} BMPImageHeader;
CTexture::CTexture(int w, int h, int fmt) :
width(w),
height(h),
format(fmt)
{
cmap = NULL;
cmapEntries = 0;
switch (format)
{
case GL_RGB:
case GL_BGR_EXT:
components = 3;
break;
case GL_RGBA:
components = 4;
break;
case GL_ALPHA:
components = 1;
break;
case GL_LUMINANCE:
components = 1;
break;
case GL_LUMINANCE_ALPHA:
components = 2;
break;
default:
break;
}
pixels = new unsigned char[width * height * components];
glName = 0;
}
CTexture::~CTexture()
{
if (pixels != NULL)
delete[] pixels;
if (cmap != NULL)
delete[] cmap;
}
void CTexture::bindName()
{
if (pixels == NULL)
return;
GLuint tn;
glGenTextures(1, &tn);
glBindTexture(GL_TEXTURE_2D, tn);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D,
components,
width, height,
format,
GL_UNSIGNED_BYTE,
pixels);
glName = tn;
delete pixels;
}
unsigned int CTexture::getName()
{
return glName;
}
CTexture* CreateProceduralTexture(int width, int height,
int format,
ProceduralTexEval func)
{
CTexture* tex = new CTexture(width, height, format);
if (tex == NULL)
return NULL;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float u = (float) x / (float) width * 2 - 1;
float v = (float) y / (float) height * 2 - 1;
func(u, v, 0, tex->pixels + (y * width + x) * tex->components);
}
}
return tex;
}
CTexture* LoadTextureFromFile(string filename)
{
int extPos = filename.length() - 3;
if (extPos < 0)
extPos = 0;
string ext = string(filename, extPos, 3);
if (ext.compare("JPG") == 0 || ext.compare("jpg") == 0)
return CreateJPEGTexture(filename.c_str());
else if (ext.compare("BMP") == 0 || ext.compare("bmp") == 0)
return CreateBMPTexture(filename.c_str());
else
return NULL;
}
CTexture* CreateJPEGTexture(const char* filename,
int channels)
{
#ifndef JPEG_SUPPORT
return NULL;
#else
JPEG_CORE_PROPERTIES jpegProps;
printf("Reading texture: %s\n", filename);
// Must specify at least one of color or alpha
if (channels == 0)
return NULL;
ZeroMemory(&jpegProps, sizeof(JPEG_CORE_PROPERTIES));
if (ijlInit(&jpegProps) != IJL_OK)
return NULL;
jpegProps.JPGFile = (char*) filename;
if (ijlRead(&jpegProps, IJL_JFILE_READPARAMS) != IJL_OK)
{
ijlFree(&jpegProps);
return NULL;
}
// Set up the JPG color space, guessing based on the number of
// color channels.
switch (jpegProps.JPGChannels)
{
case 1:
jpegProps.JPGColor = IJL_G;
break;
case 3:
jpegProps.JPGColor = IJL_YCBCR;
break;
default:
jpegProps.JPGColor = (IJL_COLOR) IJL_OTHER;
break;
}
// Set up the target color space
int format;
if (jpegProps.JPGColor == IJL_YCBCR)
{
if ((channels & CTexture::AlphaChannel) != 0)
format = GL_RGBA;
else
format = GL_RGB;
jpegProps.DIBChannels = 3;
jpegProps.DIBColor = IJL_RGB;
}
else if (jpegProps.JPGColor == IJL_G)
{
if ((channels & CTexture::AlphaChannel) != 0)
format = GL_LUMINANCE_ALPHA;
else
format = GL_LUMINANCE;
jpegProps.DIBChannels = 1;
jpegProps.DIBColor = IJL_G;
}
else
{
ijlFree(&jpegProps);
return NULL;
}
// Create the texture
CTexture* tex = new CTexture(jpegProps.JPGWidth, jpegProps.JPGHeight,
format);
if (tex == NULL)
{
ijlFree(&jpegProps);
return NULL;
}
jpegProps.DIBBytes = tex->pixels;
jpegProps.DIBWidth = tex->width;
jpegProps.DIBHeight = tex->height;
// Slurp the body of the image
if (ijlRead(&jpegProps, IJL_JFILE_READWHOLEIMAGE) != IJL_OK)
{
printf("Failed to read texture\n");
ijlFree(&jpegProps);
delete tex;
return NULL;
}
ijlFree(&jpegProps);
// If necessary, synthesize an alpha channel from color information
if ((channels & CTexture::AlphaChannel) != 0)
{
if (format == GL_LUMINANCE_ALPHA)
{
int nPixels = tex->width * tex->height;
unsigned char *newPixels = new unsigned char[nPixels * 2];
for (int i = 0; i < nPixels; i++)
{
newPixels[i * 2] = newPixels[i * 2 + 1] = tex->pixels[i];
}
delete[] tex->pixels;
tex->pixels = newPixels;
}
}
return tex;
#endif // JPEG_SUPPORT
}
static int readInt(ifstream& in)
{
unsigned char b[4];
in.read(reinterpret_cast<char*>(b), 4);
return ((int) b[3] << 24) + ((int) b[2] << 16)
+ ((int) b[1] << 8) + (int) b[0];
}
static short readShort(ifstream& in)
{
unsigned char b[2];
in.read(reinterpret_cast<char*>(b), 2);
return ((short) b[1] << 8) + (short) b[0];
}
static CTexture* CreateBMPTexture(ifstream& in)
{
BMPFileHeader fileHeader;
BMPImageHeader imageHeader;
unsigned char* pixels;
printf("*** CreateBMPTexture\n");
in >> fileHeader.b;
in >> fileHeader.m;
fileHeader.size = readInt(in);
fileHeader.reserved = readInt(in);
fileHeader.offset = readInt(in);
printf("Checking header . . .\n");
if (fileHeader.b != 'B' || fileHeader.m != 'M')
return NULL;
printf("Header is correct.\n");
printf("File size: %d\n", fileHeader.size);
printf("Bytes read: %d\n", in.tellg());
imageHeader.size = readInt(in);
imageHeader.width = readInt(in);
imageHeader.height = readInt(in);
imageHeader.planes = readShort(in);
imageHeader.bpp = readShort(in);
imageHeader.compression = readInt(in);
imageHeader.imageSize = readInt(in);
imageHeader.widthPPM = readInt(in);
imageHeader.heightPPM = readInt(in);
imageHeader.colorsUsed = readInt(in);
imageHeader.colorsImportant = readInt(in);
printf("%d Planes @ %d BPP\n", imageHeader.planes, imageHeader.bpp);
printf("Size: %d\n", imageHeader.size);
printf("Dimensions: %d x %d\n", imageHeader.width, imageHeader.height);
if (imageHeader.width <= 0 || imageHeader.height <= 0)
return NULL;
// We currently don't support compressed BMPs
if (imageHeader.compression != 0)
return NULL;
// We don't handle 1-, 2-, or 4-bpp images
if (imageHeader.bpp != 8 && imageHeader.bpp != 24 && imageHeader.bpp != 32)
return NULL;
printf("Image size: %d\n", imageHeader.imageSize);
printf("Compression: %d\n", imageHeader.compression);
printf("WidthPPM x HeightPPM: %d x %d\n", imageHeader.widthPPM, imageHeader.heightPPM);
unsigned char* palette = NULL;
if (imageHeader.bpp == 8)
{
printf("Reading %d color palette\n", imageHeader.colorsUsed);
palette = new unsigned char[imageHeader.colorsUsed * 4];
in.read(reinterpret_cast<char*>(palette), imageHeader.colorsUsed * 4);
}
in.seekg(fileHeader.offset, ios_base::beg);
unsigned int bytesPerRow =
(imageHeader.width * imageHeader.bpp / 8 + 1) & ~1;
unsigned int imageBytes = bytesPerRow * imageHeader.height;
// slurp the image data
pixels = new unsigned char[imageBytes];
in.read(reinterpret_cast<char*>(pixels), imageBytes);
// check for truncated file
CTexture* tex = new CTexture(imageHeader.width, imageHeader.height,
GL_RGB);
if (tex == NULL)
{
delete[] pixels;
return NULL;
}
// copy the image into the texture and perform any necessary conversions
for (int y = 0; y < imageHeader.height; y++)
{
unsigned char* src = &pixels[y * bytesPerRow];
unsigned char* dst = &tex->pixels[y * tex->width * 3];
switch (imageHeader.bpp)
{
case 8:
{
for (int x = 0; x < imageHeader.width; x++)
{
unsigned char* color = palette + (*src << 2);
dst[0] = color[2];
dst[1] = color[1];
dst[2] = color[0];
src++;
dst += 3;
}
}
break;
case 24:
{
for (int x = 0; x < imageHeader.width; x++)
{
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
src += 3;
dst += 3;
}
}
break;
case 32:
{
for (int x = 0; x < imageHeader.width; x++)
{
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
src += 4;
dst += 3;
}
}
break;
}
}
delete[] pixels;
return tex;
}
CTexture* CreateBMPTexture(const char* filename)
{
ifstream bmpFile(filename, ios::in | ios::binary);
if (bmpFile.good())
{
CTexture* tex = CreateBMPTexture(bmpFile);
bmpFile.close();
return tex;
}
else
{
return NULL;
}
}

58
src/texture.h 100644
View File

@ -0,0 +1,58 @@
// texture.h
//
// Copyright (C) 2001, Chris Laurel
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _TEXTURE_H_
#define _TEXTURE_H_
#include <string>
using namespace std;
typedef void (*ProceduralTexEval)(float, float, float, unsigned char*);
class CTexture
{
public:
CTexture(int w, int h, int fmt);
~CTexture();
void bindName();
unsigned int getName();
enum {
ColorChannel = 1,
AlphaChannel = 2
};
public:
int width;
int height;
int components;
int format;
unsigned char* pixels;
int cmapEntries;
int cmapFormat;
unsigned char* cmap;
unsigned int glName;
};
extern CTexture* CreateProceduralTexture(int width, int height,
int format,
ProceduralTexEval func);
extern CTexture* CreateJPEGTexture(const char* filename,
int channels = CTexture::ColorChannel);
extern CTexture* CreateBMPTexture(const char* filename);
extern CTexture* LoadTextureFromFile(string filename);
#endif // _TEXTURE_H_

374
src/tokenizer.cpp 100644
View File

@ -0,0 +1,374 @@
// tokenizer.cpp
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cctype>
#include <cmath>
#include "tokenizer.h"
static bool issep(char c)
{
return !isdigit(c) && !isalpha(c) && c != '.';
}
Tokenizer::Tokenizer(istream* _in) :
in(_in),
haveValidName(false),
haveValidNumber(false),
haveValidString(false),
tokenType(TokenBegin),
pushedBack(false)
{
}
Tokenizer::TokenType Tokenizer::nextToken()
{
bool complete = false;
State state = StartState;
TokenType type = TokenNull;
if (pushedBack)
{
pushedBack = false;
return tokenType;
}
textToken = "";
haveValidNumber = false;
haveValidName = false;
haveValidString = false;
if (tokenType == TokenBegin)
{
nextChar = readChar();
if (in->eof())
return TokenEnd;
}
else if (tokenType == TokenEnd)
{
return tokenType;
}
double integerValue = 0;
double fractionValue = 0;
double fracExp = 1;
double exponentValue = 0;
double exponentSign = 1;
TokenType newToken = TokenBegin;
while (newToken == TokenBegin)
{
switch (state)
{
case StartState:
if (isspace(nextChar))
{
state = StartState;
}
else if (isdigit(nextChar))
{
state = NumberState;
integerValue = (int) nextChar - (int) '0';
}
else if (isalpha(nextChar))
{
state = NameState;
textToken += (char) nextChar;
}
else if (nextChar == '#')
{
state = CommentState;
}
else if (nextChar == '"')
{
state = StringState;
}
else if (nextChar == '{')
{
newToken = TokenBeginGroup;
nextChar = readChar();
}
else if (nextChar == '}')
{
newToken = TokenEndGroup;
nextChar = readChar();
}
else if (nextChar == '[')
{
newToken = TokenBeginArray;
nextChar = readChar();
}
else if (nextChar == ']')
{
newToken = TokenEndArray;
nextChar = readChar();
}
else if (nextChar == '=')
{
newToken = TokenEquals;
nextChar = readChar();
}
else if (nextChar == -1)
{
newToken = TokenEnd;
}
else
{
newToken = TokenError;
syntaxError("Bad character in stream");
}
break;
case NameState:
if (isalpha(nextChar) || isdigit(nextChar))
{
state = NameState;
textToken += (char) nextChar;
}
else
{
newToken = TokenName;
haveValidName = true;
}
break;
case CommentState:
if (nextChar == '\n' || nextChar == '\r')
state = StartState;
break;
case StringState:
if (nextChar != '"')
{
state = StringState;
textToken += (char) nextChar;
}
else
{
newToken = TokenString;
haveValidString = true;
nextChar = readChar();
}
break;
case NumberState:
if (isdigit(nextChar))
{
state = NumberState;
integerValue = integerValue * 10 + (int) nextChar - (int) '0';
}
else if (nextChar == '.')
{
state = FractionState;
}
else if (nextChar == 'e' || nextChar == 'E')
{
state = ExponentFirstState;
}
else if (issep(nextChar))
{
newToken = TokenNumber;
haveValidNumber = true;
}
else
{
newToken = TokenError;
syntaxError("Bad character in number");
}
break;
case FractionState:
if (isdigit(nextChar))
{
state = FractionState;
fractionValue = fractionValue * 10 + nextChar - (int) '0';
fracExp *= 10;
}
else if (nextChar == 'e' || nextChar == 'E')
{
state = ExponentFirstState;
}
else if (issep(nextChar))
{
newToken = TokenNumber;
haveValidNumber = true;
} else {
newToken = TokenError;
syntaxError("Bad character in number");
}
break;
case ExponentFirstState:
if (isdigit(nextChar))
{
state = ExponentState;
exponentValue = (int) nextChar - (int) '0';
}
else if (nextChar == '-')
{
state = ExponentState;
exponentSign = -1;
}
else if (nextChar == '+')
{
state = ExponentState;
}
else
{
state = ErrorState;
syntaxError("Bad character in number");
}
break;
case ExponentState:
if (isdigit(nextChar))
{
state = ExponentState;
exponentValue = exponentValue * 10 + (int) nextChar - (int) '0';
}
else if (issep(nextChar))
{
newToken = TokenNumber;
haveValidNumber = true;
}
else
{
state = ErrorState;
syntaxError("Bad character in number");
}
break;
case DotState:
if (isdigit(nextChar))
{
state = FractionState;
fractionValue = fractionValue * 10 + (int) nextChar - (int) '0';
fracExp = 10;
}
else
{
state = ErrorState;
syntaxError("'.' in stupid place");
}
break;
}
if (newToken == TokenBegin)
{
nextChar = readChar();
}
}
tokenType = newToken;
if (haveValidNumber)
{
numberValue = integerValue + fractionValue / fracExp;
if (exponentValue != 0)
numberValue *= pow(10, exponentValue * exponentSign);
}
return tokenType;
}
Tokenizer::TokenType Tokenizer::getTokenType()
{
return tokenType;
}
void Tokenizer::pushBack()
{
pushedBack = true;
}
double Tokenizer::getNumberValue()
{
return numberValue;
}
string Tokenizer::getNameValue()
{
return textToken;
}
string Tokenizer::getStringValue()
{
return textToken;
}
int Tokenizer::readChar()
{
return (char) in->get();
}
void Tokenizer::syntaxError(char* message)
{
cerr << message << '\n';
}
int Tokenizer::getLineNumber()
{
return 0;
}
#if 0
// Tokenizer test
int main(int argc, char *argv[])
{
Tokenizer tokenizer(&cin);
Tokenizer::TokenType tok = Tokenizer::TokenBegin;
while (tok != Tokenizer::TokenEnd)
{
tok = tokenizer.nextToken();
switch (tok)
{
case Tokenizer::TokenBegin:
cout << "Begin";
break;
case Tokenizer::TokenEnd:
cout << "End";
break;
case Tokenizer::TokenName:
cout << "Name = " << tokenizer.getNameValue();
break;
case Tokenizer::TokenNumber:
cout << "Number = " << tokenizer.getNumberValue();
break;
case Tokenizer::TokenString:
cout << "String = " << '"' << tokenizer.getStringValue() << '"';
break;
case Tokenizer::TokenBeginGroup:
cout << '{';
break;
case Tokenizer::TokenEndGroup:
cout << '}';
break;
case Tokenizer::TokenEquals:
cout << '=';
break;
default:
cout << "Other";
break;
}
cout << '\n';
}
return 0;
}
#endif

82
src/tokenizer.h 100644
View File

@ -0,0 +1,82 @@
// tokenizer.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _TOKENIZER_H_
#define _TOKENIZER_H_
#include <string>
#include <iostream>
using namespace std;
class Tokenizer
{
public:
enum TokenType
{
TokenName = 0,
TokenString = 1,
TokenNumber = 2,
TokenBegin = 3,
TokenEnd = 4,
TokenNull = 5,
TokenBeginGroup = 6,
TokenEndGroup = 7,
TokenBeginArray = 8,
TokenEndArray = 9,
TokenEquals = 10,
TokenError = 11,
};
Tokenizer(istream*);
TokenType nextToken();
TokenType getTokenType();
void pushBack();
double getNumberValue();
string getNameValue();
string getStringValue();
int getLineNumber();
private:
enum State
{
StartState = 0,
NameState = 1,
NumberState = 2,
FractionState = 3,
ExponentState = 4,
ExponentFirstState = 5,
DotState = 6,
CommentState = 7,
StringState = 8,
ErrorState = 9,
};
istream* in;
int nextChar;
TokenType tokenType;
bool haveValidNumber;
bool haveValidName;
bool haveValidString;
bool pushedBack;
int readChar();
void syntaxError(char*);
double numberValue;
string textToken;
};
#endif // _TOKENIZER_H_

178
src/trilist.cpp 100644
View File

@ -0,0 +1,178 @@
// trilist.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// A very simple triangle list class for quickie OpenGL programs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "gl.h"
#include "trilist.h"
TriangleList::TriangleList() :
nTriangles(0),
maxTriangles(0),
vertices(NULL),
normals(NULL),
color(1, 1, 1),
colorMode(0),
bboxValid(true)
{
}
TriangleList::~TriangleList()
{
if (vertices != NULL)
delete[] vertices;
if (normals != NULL)
delete[] normals;
}
void TriangleList::clear()
{
nTriangles = 0;
}
void TriangleList::render()
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glNormalPointer(GL_FLOAT, 0, normals);
if (colorMode == 1)
glColor4f(color.x, color.y, color.z, 1);
glDrawArrays(GL_TRIANGLES, 0, nTriangles * 3);
}
// Add a triangle with vertex normals
void TriangleList::addTriangle(Point3f& p0, Vec3f& n0,
Point3f& p1, Vec3f& n1,
Point3f& p2, Vec3f& n2)
{
if (nTriangles == maxTriangles)
{
if (maxTriangles == 0)
{
maxTriangles = 16;
vertices = new float[maxTriangles * 9];
normals = new float[maxTriangles * 9];
}
else
{
float* newVertices = new float[maxTriangles * 2 * 9];
memcpy((void*) newVertices,
(void*) vertices,
sizeof(float) * maxTriangles * 9);
delete vertices;
vertices = newVertices;
float* newNormals = new float[maxTriangles * 2 * 9];
memcpy((void*) newNormals,
(void*) normals,
sizeof(float) * maxTriangles * 9);
delete normals;
normals = newNormals;
maxTriangles *= 2;
}
}
int n = nTriangles * 9;
vertices[n ] = p0.x;
vertices[n + 1] = p0.y;
vertices[n + 2] = p0.z;
vertices[n + 3] = p1.x;
vertices[n + 4] = p1.y;
vertices[n + 5] = p1.z;
vertices[n + 6] = p2.x;
vertices[n + 7] = p2.y;
vertices[n + 8] = p2.z;
normals[n ] = n0.x;
normals[n + 1] = n0.y;
normals[n + 2] = n0.z;
normals[n + 3] = n1.x;
normals[n + 4] = n1.y;
normals[n + 5] = n1.z;
normals[n + 6] = n2.x;
normals[n + 7] = n2.y;
normals[n + 8] = n2.z;
nTriangles++;
bboxValid = false;
}
// Add a triangle with the specified face normal
void TriangleList::addTriangle(Point3f& p0, Point3f& p1, Point3f& p2,
Vec3f& normal)
{
addTriangle(p0, normal, p1, normal, p2, normal);
}
// Add a triangle, normal is computed automatically
void TriangleList::addTriangle(Point3f& p0, Point3f& p1, Point3f& p2)
{
// Compute the normal
Vec3f dv0 = p1 - p0;
Vec3f dv1 = p2 - p1;
Vec3f normal = cross(dv0, dv1);
normal.normalize();
addTriangle(p0, p1, p2, normal);
}
int TriangleList::triangleCount()
{
return nTriangles;
}
Vec3f TriangleList::getColor() const
{
return color;
}
void TriangleList::setColor(Vec3f _color)
{
color = _color;
}
void TriangleList::setColorMode(int _colorMode)
{
colorMode = _colorMode;
}
// Apply a translation and uniform scale to the vertices
void TriangleList::transform(Vec3f move, float scale)
{
printf("TriangleList::transform : scale = %f\n", scale);
for (int i = 0; i < nTriangles * 3; i++)
{
int n = i * 3;
vertices[n ] = (vertices[n ] - move.x) * scale;
vertices[n + 1] = (vertices[n + 1] - move.y) * scale;
vertices[n + 2] = (vertices[n + 2] - move.z) * scale;
}
}
AxisAlignedBox TriangleList::getBoundingBox()
{
if (!bboxValid)
{
bbox = AxisAlignedBox();
for (int i = 0; i < nTriangles * 9; i += 3)
bbox.include(Point3f(vertices[i], vertices[i + 1], vertices[i + 2]));
}
return bbox;
}

60
src/trilist.h 100644
View File

@ -0,0 +1,60 @@
// trilist.h
//
// Copyright (C) 2001, Chris Laurel
//
// A very simple triangle list class for quickie OpenGL programs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _TRILIST_H_
#define _TRILIST_H_
#include "vecmath.h"
#include "aabox.h"
class TriangleList
{
public:
TriangleList();
~TriangleList();
void clear();
void addTriangle(Point3f&, Vec3f&,
Point3f&, Vec3f&,
Point3f&, Vec3f&);
void addTriangle(Point3f&, Point3f&, Point3f&, Vec3f&);
void addTriangle(Point3f&, Point3f&, Point3f&);
void render();
int triangleCount();
Vec3f getColor() const;
void setColor(Vec3f);
void setColorMode(int);
// Apply a translation and uniform scale to the vertices
void transform(Vec3f move, float scale);
AxisAlignedBox getBoundingBox();
private:
// Override the default copy constructor
TriangleList(TriangleList& tl) {};
private:
int nTriangles;
int maxTriangles;
float *vertices;
float *normals;
int colorMode;
Vec3f color;
bool bboxValid;
AxisAlignedBox bbox;
};
#endif // _TRILIST_H_

108
src/univcoord.cpp 100644
View File

@ -0,0 +1,108 @@
// univcoord.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "univcoord.h"
UniversalCoord::UniversalCoord()
{
}
UniversalCoord::UniversalCoord(BigFix _x, BigFix _y, BigFix _z) :
x(_x), y(_y), z(_z)
{
}
UniversalCoord::UniversalCoord(double _x, double _y, double _z) :
x(_x), y(_y), z(_z)
{
}
UniversalCoord::UniversalCoord(Point3d& p) :
x(p.x), y(p.y), z(p.z)
{
}
UniversalCoord::UniversalCoord(Point3f& p) :
x(p.x), y(p.y), z(p.z)
{
}
UniversalCoord::operator Point3d() const
{
return Point3d((double) x, (double) y, (double) z);
}
UniversalCoord::operator Point3f() const
{
return Point3f((float) x, (float) y, (float) z);
}
Vec3d operator-(const UniversalCoord uc0, const UniversalCoord uc1)
{
return Vec3d((double) (uc0.x - uc1.x),
(double) (uc0.y - uc1.y),
(double) (uc0.z - uc1.z));
}
Vec3d operator-(const UniversalCoord uc, const Point3d p)
{
return Vec3d((double) (uc.x - (BigFix) p.x),
(double) (uc.y - (BigFix) p.y),
(double) (uc.z - (BigFix) p.z));
}
Vec3d operator-(const Point3d p, const UniversalCoord uc)
{
return Vec3d((double) ((BigFix) p.x - uc.x),
(double) ((BigFix) p.y - uc.y),
(double) ((BigFix) p.z - uc.z));
}
Vec3f operator-(const UniversalCoord uc, const Point3f p)
{
return Vec3f((float) (uc.x - (BigFix) p.x),
(float) (uc.y - (BigFix) p.y),
(float) (uc.z - (BigFix) p.z));
}
Vec3f operator-(const Point3f p, const UniversalCoord uc)
{
return Vec3f((float) ((BigFix) p.x - uc.x),
(float) ((BigFix) p.y - uc.y),
(float) ((BigFix) p.z - uc.z));
}
UniversalCoord operator+(const UniversalCoord uc, const Vec3d v)
{
return UniversalCoord(uc.x + BigFix(v.x),
uc.y + BigFix(v.y),
uc.z + BigFix(v.z));
}
UniversalCoord operator+(const UniversalCoord uc, const Vec3f v)
{
return UniversalCoord(uc.x + BigFix((double) v.x),
uc.y + BigFix((double) v.y),
uc.z + BigFix((double) v.z));
}
UniversalCoord operator-(const UniversalCoord uc, const Vec3d v)
{
return UniversalCoord(uc.x - BigFix(v.x),
uc.y - BigFix(v.y),
uc.z - BigFix(v.z));
}
UniversalCoord operator-(const UniversalCoord uc, const Vec3f v)
{
return UniversalCoord(uc.x - BigFix((double) v.x),
uc.y - BigFix((double) v.y),
uc.z - BigFix((double) v.z));
}

56
src/univcoord.h 100644
View File

@ -0,0 +1,56 @@
// univcoord.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Universal coordinate is a high-precision fixed point coordinate for
// locating objects in 3D space on scales ranging from millimeters to
// thousands of light years.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _UNIVCOORD_H_
#define _UNIVCOORD_H_
#include "bigfix.h"
#include "vecmath.h"
class UniversalCoord
{
public:
UniversalCoord();
UniversalCoord(BigFix, BigFix, BigFix);
UniversalCoord(double, double, double);
UniversalCoord(Point3d&);
UniversalCoord(Point3f&);
operator Point3d() const;
operator Point3f() const;
friend Vec3d operator-(const UniversalCoord, const UniversalCoord);
friend Vec3d operator-(const UniversalCoord, const Point3d);
friend Vec3d operator-(const Point3d, const UniversalCoord);
friend Vec3f operator-(const UniversalCoord, const Point3f);
friend Vec3f operator-(const Point3f, const UniversalCoord);
friend UniversalCoord operator+(const UniversalCoord, const Vec3d);
friend UniversalCoord operator+(const UniversalCoord, const Vec3f);
friend UniversalCoord operator-(const UniversalCoord, const Vec3d);
friend UniversalCoord operator-(const UniversalCoord, const Vec3f);
BigFix x, y, z;
};
Vec3d operator-(const UniversalCoord, const UniversalCoord);
Vec3d operator-(const UniversalCoord, const Point3d);
Vec3d operator-(const Point3d, const UniversalCoord);
Vec3f operator-(const UniversalCoord, const Point3f);
Vec3f operator-(const Point3f, const UniversalCoord);
UniversalCoord operator+(const UniversalCoord, const Vec3d);
UniversalCoord operator+(const UniversalCoord, const Vec3f);
UniversalCoord operator-(const UniversalCoord, const Vec3d);
UniversalCoord operator-(const UniversalCoord, const Vec3f);
#endif // _UNIVCOORD_H_

88
src/vecgl.h 100644
View File

@ -0,0 +1,88 @@
// vecgl.h
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// Overloaded versions of GL functions
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _VECGL_H_
#define _VECGL_H_
#include "vecmath.h"
#include "quaternion.h"
#include "color.h"
inline void glVertex(const Point3f& p)
{
glVertex3fv(&p.x);
}
inline void glVertex(const Vec3f& v)
{
glVertex3fv(&v.x);
}
inline void glNormal(const Vec3f& n)
{
glNormal3fv(&n.x);
}
inline void glTexCoord(const Point2f& p)
{
glTexCoord2fv(&p.x);
}
inline void glColor(const Color& c)
{
glColor4f(c.red(), c.green(), c.blue(), c.alpha());
}
inline void glColor(const Color& c, float a)
{
glColor4f(c.red(), c.green(), c.blue(), c.alpha() * a);
}
inline void glRotate(const Quatf& q)
{
Vec3f axis;
float angle;
q.getAxisAngle(axis, angle);
glRotatef(radToDeg(angle), axis.x, axis.y, axis.z);
}
inline void glTranslate(const Vec3f& v)
{
glTranslatef(v.x, v.y, v.z);
}
inline void glTranslate(const Point3f& p)
{
glTranslatef(p.x, p.y, p.z);
}
inline void glLightDirection(int light, Vec3f& dir)
{
glLightfv(light, GL_POSITION, &(Vec4f(dir.x, dir.y, dir.z, 0.0f).x));
}
inline void glLightPosition(int light, Point3f& pos)
{
glLightfv(light, GL_POSITION, &(Vec4f(pos.x, pos.y, pos.z, 1.0f).x));
}
inline void glLightColor(int light, int which, Vec3f& color)
{
glLightfv(light, which, &(Vec4f(color.x, color.y, color.z, 1.0f).x));
}
inline void glLightColor(int light, int which, Vec4f& color)
{
glLightfv(light, which, &color.x);
}
#endif // _VECGL_H_

972
src/vecmath.h 100644
View File

@ -0,0 +1,972 @@
// vecmath.h
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// Basic templatized vector and matrix math library.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _VECMATH_H_
#define _VECMATH_H_
#include <cmath>
template<class T> class Point3;
template<class T> class Vector3
{
public:
inline Vector3();
inline Vector3(const Vector3<T>&);
inline Vector3(T, T, T);
inline T& operator[](int) const;
inline Vector3& operator+=(const Vector3<T>&);
inline Vector3& operator-=(const Vector3<T>&);
inline Vector3& operator*=(T);
inline Vector3 operator-();
inline Vector3 operator+();
inline T length() const;
inline void normalize();
T x, y, z;
};
template<class T> class Point3
{
public:
inline Point3();
inline Point3(const Point3&);
inline Point3(T, T, T);
inline T& operator[](int) const;
inline Point3& operator+=(const Vector3<T>&);
inline Point3& operator-=(const Vector3<T>&);
inline Point3& operator*=(T);
inline T distanceTo(const Point3&) const;
inline T distanceToSquared(const Point3&) const;
T x, y, z;
};
template<class T> class Point2;
template<class T> class Vector2
{
public:
inline Vector2();
inline Vector2(T, T);
T x, y;
};
template<class T> class Point2
{
public:
inline Point2();
inline Point2(T, T);
T x, y;
};
template<class T> class Vector4
{
public:
inline Vector4();
inline Vector4(T, T, T, T);
inline T& operator[](int) const;
inline Vector4& operator+=(const Vector4&);
inline Vector4& operator-=(const Vector4&);
inline Vector4& operator*=(T);
inline Vector4 operator-();
inline Vector4 operator+();
T x, y, z, w;
};
template<class T> class Matrix4
{
public:
Matrix4();
Matrix4(const Vector4<T>&, const Vector4<T>&,
const Vector4<T>&, const Vector4<T>&);
inline const Vector4<T>& operator[](int) const;
inline Vector4<T> row(int) const;
inline Vector4<T> column(int) const;
static Matrix4<T> identity();
static Matrix4<T> translation(const Point3<T>&);
static Matrix4<T> translation(const Vector3<T>&);
static Matrix4<T> rotation(const Vector3<T>&, T);
static Matrix4<T> xrotation(T);
static Matrix4<T> yrotation(T);
static Matrix4<T> zrotation(T);
static Matrix4<T> scaling(const Vector3<T>&);
static Matrix4<T> scaling(T);
void translate(const Point3<T>&);
Matrix4<T> transpose() const;
Vector4<T> r[4];
};
template<class T> class Matrix3
{
public:
Matrix3();
Matrix3(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&);
template<class U> Matrix3(const Matrix3<U>&);
static Matrix3<T> xrotation(T);
static Matrix3<T> yrotation(T);
static Matrix3<T> zrotation(T);
inline const Vector3<T>& operator[](int) const;
inline Vector3<T> row(int) const;
inline Vector3<T> column(int) const;
inline Matrix3& operator*=(T);
static Matrix3<T> identity();
Matrix3<T> transpose() const;
Matrix3<T> inverse() const;
T determinant() const;
// template<class U> operator Matrix3<U>() const;
Vector3<T> r[3];
};
typedef Vector3<float> Vec3f;
typedef Vector3<double> Vec3d;
typedef Point3<float> Point3f;
typedef Point3<double> Point3d;
typedef Vector2<float> Vec2f;
typedef Point2<float> Point2f;
typedef Vector4<float> Vec4f;
typedef Vector4<double> Vec4d;
typedef Matrix4<float> Mat4f;
typedef Matrix4<double> Mat4d;
typedef Matrix3<float> Mat3f;
typedef Matrix3<double> Mat3d;
//**** Vector3 constructors
template<class T> Vector3<T>::Vector3() : x(0), y(0), z(0)
{
}
template<class T> Vector3<T>::Vector3(const Vector3<T>& v) :
x(v.x), y(v.y), z(v.z)
{
}
template<class T> Vector3<T>::Vector3(T _x, T _y, T _z) : x(_x), y(_y), z(_z)
{
}
//**** Vector3 operators
template<class T> T& Vector3<T>::operator[](int n) const
{
// Not portable--I'll write a new version when I try to compile on a
// platform where it bombs.
return ((T*) this)[n];
}
template<class T> Vector3<T>& Vector3<T>::operator+=(const Vector3<T>& a)
{
x += a.x; y += a.y; z += a.z;
return *this;
}
template<class T> Vector3<T>& Vector3<T>::operator-=(const Vector3<T>& a)
{
x -= a.x; y -= a.y; z -= a.z;
return *this;
}
template<class T> Vector3<T>& Vector3<T>::operator*=(T s)
{
x *= s; y *= s; z *= s;
return *this;
}
template<class T> Vector3<T> Vector3<T>::operator-()
{
return Vector3<T>(-x, -y, -z);
}
template<class T> Vector3<T> Vector3<T>::operator+()
{
return *this;
}
template<class T> Vector3<T> operator+(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
}
template<class T> Vector3<T> operator-(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
}
template<class T> Vector3<T> operator*(T s, const Vector3<T>& v)
{
return Vector3<T>(s * v.x, s * v.y, s * v.z);
}
template<class T> Vector3<T> operator*(const Vector3<T>& v, T s)
{
return Vector3<T>(s * v.x, s * v.y, s * v.z);
}
// dot product
template<class T> T operator*(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
// cross product
template<class T> Vector3<T> operator^(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
template<class T> bool operator==(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x == b.x && a.y == b.y && a.z == b.z;
}
template<class T> bool operator!=(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x != b.x || a.y != b.y || a.z != b.z;
}
template<class T> Vector3<T> operator/(const Vector3<T>& v, T s)
{
T is = 1 / s;
return Vector3<T>(is * v.x, is * v.y, is * v.z);
}
template<class T> T dot(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
template<class T> Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
template<class T> T Vector3<T>::length() const
{
return (T) sqrt(x * x + y * y + z * z);
}
template<class T> void Vector3<T>::normalize()
{
T s = 1 / (T) sqrt(x * x + y * y + z * z);
x *= s;
y *= s;
z *= s;
}
//**** Point3 constructors
template<class T> Point3<T>::Point3() : x(0), y(0), z(0)
{
}
template<class T> Point3<T>::Point3(const Point3<T>& p) :
x(p.x), y(p.y), z(p.z)
{
}
template<class T> Point3<T>::Point3(T _x, T _y, T _z) : x(_x), y(_y), z(_z)
{
}
//**** Point3 operators
template<class T> T& Point3<T>::operator[](int n) const
{
// Not portable--I'll write a new version when I try to compile on a
// platform where it bombs.
return ((T*) this)[n];
}
template<class T> Vector3<T> operator-(const Point3<T>& a, const Point3<T>& b)
{
return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
}
template<class T> Point3<T>& Point3<T>::operator+=(const Vector3<T>& v)
{
x += v.x; y += v.y; z += v.z;
return *this;
}
template<class T> Point3<T>& Point3<T>::operator-=(const Vector3<T>& v)
{
x -= v.x; y -= v.y; z -= v.z;
return *this;
}
template<class T> Point3<T>& Point3<T>::operator*=(T s)
{
x *= s; y *= s; z *= s;
return *this;
}
template<class T> bool operator==(const Point3<T>& a, const Point3<T>& b)
{
return a.x == b.x && a.y == b.y && a.z == b.z;
}
template<class T> bool operator!=(const Point3<T>& a, const Point3<T>& b)
{
return a.x != b.x || a.y != b.y || a.z != b.z;
}
template<class T> Point3<T> operator+(const Point3<T>& p, const Vector3<T>& v)
{
return Point3<T>(p.x + v.x, p.y + v.y, p.z + v.z);
}
template<class T> Point3<T> operator-(const Point3<T>& p, const Vector3<T>& v)
{
return Point3<T>(p.x - v.x, p.y - v.y, p.z - v.z);
}
// Naughty naughty . . . remove these since they aren't proper
// point methods--changing the implicit homogenous coordinate isn't
// allowed.
template<class T> Point3<T> operator*(const Point3<T>& p, T s)
{
return Point3<T>(p.x * s, p.y * s, p.z * s);
}
template<class T> Point3<T> operator*(T s, const Point3<T>& p)
{
return Point3<T>(p.x * s, p.y * s, p.z * s);
}
//**** Point3 methods
template<class T> T Point3<T>::distanceTo(const Point3& p) const
{
return (T) sqrt((p.x - x) * (p.x - x) +
(p.y - y) * (p.y - y) +
(p.z - z) * (p.z - z));
}
template<class T> T Point3<T>::distanceToSquared(const Point3& p) const
{
return ((p.x - x) * (p.x - x) +
(p.y - y) * (p.y - y) +
(p.z - z) * (p.z - z));
}
//**** Vector2 constructors
template<class T> Vector2<T>::Vector2() : x(0), y(0)
{
}
template<class T> Vector2<T>::Vector2(T _x, T _y) : x(_x), y(_y)
{
}
//**** Vector2 operators
template<class T> bool operator==(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x == b.x && a.y == b.y;
}
template<class T> bool operator!=(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x != b.x || a.y != b.y;
}
//**** Point2 constructors
template<class T> Point2<T>::Point2() : x(0), y(0)
{
}
template<class T> Point2<T>::Point2(T _x, T _y) : x(_x), y(_y)
{
}
//**** Point2 operators
template<class T> bool operator==(const Point2<T>& a, const Point2<T>& b)
{
return a.x == b.x && a.y == b.y;
}
template<class T> bool operator!=(const Point2<T>& a, const Point2<T>& b)
{
return a.x != b.x || a.y != b.y;
}
//**** Vector4 constructors
template<class T> Vector4<T>::Vector4() : x(0), y(0), z(0), w(0)
{
}
template<class T> Vector4<T>::Vector4(T _x, T _y, T _z, T _w) :
x(_x), y(_y), z(_z), w(_w)
{
}
//**** Vector4 operators
template<class T> T& Vector4<T>::operator[](int n) const
{
// Not portable--I'll write a new version when I try to compile on a
// platform where it bombs.
return ((T*) this)[n];
}
template<class T> bool operator==(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}
template<class T> bool operator!=(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
}
template<class T> Vector4<T>& Vector4<T>::operator+=(const Vector4<T>& a)
{
x += a.x; y += a.y; z += a.z; w += a.w;
return *this;
}
template<class T> Vector4<T>& Vector4<T>::operator-=(const Vector4<T>& a)
{
x -= a.x; y -= a.y; z -= a.z; w -= a.w;
return *this;
}
template<class T> Vector4<T>& Vector4<T>::operator*=(T s)
{
x *= s; y *= s; z *= s; w *= s;
return *this;
}
template<class T> Vector4<T> Vector4<T>::operator-()
{
return Vector4<T>(-x, -y, -z, -w);
}
template<class T> Vector4<T> Vector4<T>::operator+()
{
return *this;
}
template<class T> Vector4<T> operator+(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
}
template<class T> Vector4<T> operator-(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
}
template<class T> Vector4<T> operator*(T s, const Vector4<T>& v)
{
return Vector4<T>(s * v.x, s * v.y, s * v.z, s * v.w);
}
template<class T> Vector4<T> operator*(const Vector4<T>& v, T s)
{
return Vector4<T>(s * v.x, s * v.y, s * v.z, s * v.w);
}
// dot product
template<class T> T operator*(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
template<class T> T dot(const Vector4<T>& a, const Vector4<T>& b)
{
return a * b;
}
//**** Matrix3 constructors
template<class T> Matrix3<T>::Matrix3()
{
r[0] = Vector3<T>(0, 0, 0);
r[1] = Vector3<T>(0, 0, 0);
r[2] = Vector3<T>(0, 0, 0);
}
template<class T> Matrix3<T>::Matrix3(const Vector3<T>& r0,
const Vector3<T>& r1,
const Vector3<T>& r2)
{
r[0] = r0;
r[1] = r1;
r[2] = r2;
}
template<class T, class U> Matrix3<T>::Matrix3(const Matrix3<U>& m)
{
#if 0
r[0] = m.r[0];
r[1] = m.r[1];
r[2] = m.r[2];
#endif
r[0].x = m.r[0].x; r[0].y = m.r[0].y; r[0].z = m.r[0].z;
r[1].x = m.r[1].x; r[1].y = m.r[1].y; r[1].z = m.r[1].z;
r[2].x = m.r[2].x; r[2].y = m.r[2].y; r[2].z = m.r[2].z;
}
//**** Matrix3 operators
template<class T> const Vector3<T>& Matrix3<T>::operator[](int n) const
{
// return const_cast<Vector3<T>&>(r[n]);
return r[n];
}
template<class T> Vector3<T> Matrix3<T>::row(int n) const
{
return r[n];
}
template<class T> Vector3<T> Matrix3<T>::column(int n) const
{
return Vector3<T>(r[0][n], r[1][n], r[2][n]);
}
template<class T> Matrix3<T>& Matrix3<T>::operator*=(T s)
{
r[0] *= s;
r[1] *= s;
r[2] *= s;
return *this;
}
// pre-multiply column vector by a 3x3 matrix
template<class T> Vector3<T> operator*(const Matrix3<T>& m, const Vector3<T>& v)
{
return Vector3<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z,
m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z,
m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z);
}
// post-multiply row vector by a 3x3 matrix
template<class T> Vector3<T> operator*(const Vector3<T>& v, const Matrix3<T>& m)
{
return Vector3<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z,
m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z,
m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z);
}
// pre-multiply column point by a 3x3 matrix
template<class T> Point3<T> operator*(const Matrix3<T>& m, const Point3<T>& p)
{
return Point3<T>(m.r[0].x * p.x + m.r[0].y * p.y + m.r[0].z * p.z,
m.r[1].x * p.x + m.r[1].y * p.y + m.r[1].z * p.z,
m.r[2].x * p.x + m.r[2].y * p.y + m.r[2].z * p.z);
}
// post-multiply row point by a 3x3 matrix
template<class T> Point3<T> operator*(const Point3<T>& p, const Matrix3<T>& m)
{
return Point3<T>(m.r[0].x * p.x + m.r[1].x * p.y + m.r[2].x * p.z,
m.r[0].y * p.x + m.r[1].y * p.y + m.r[2].y * p.z,
m.r[0].z * p.x + m.r[1].z * p.y + m.r[2].z * p.z);
}
template<class T> Matrix3<T> operator*(const Matrix3<T>& a,
const Matrix3<T>& b)
{
#define MATMUL(R, C) (a[R].x * b[0].C + a[R].y * b[1].C + a[R].z * b[2].C)
return Matrix3<T>(Vector3<T>(MATMUL(0, x), MATMUL(0, y), MATMUL(0, z)),
Vector3<T>(MATMUL(1, x), MATMUL(1, y), MATMUL(1, z)),
Vector3<T>(MATMUL(2, x), MATMUL(2, y), MATMUL(2, z)));
#undef MATMUL
}
template<class T> Matrix3<T> operator+(const Matrix3<T>& a,
const Matrix3<T>& b)
{
return Matrix3<T>(a.r[0] + b.r[0],
a.r[1] + b.r[1],
a.r[2] + b.r[2]);
}
template<class T> Matrix3<T> Matrix3<T>::identity()
{
return Matrix3<T>(Vector3<T>(1, 0, 0),
Vector3<T>(0, 1, 0),
Vector3<T>(0, 0, 1));
}
template<class T> Matrix3<T> Matrix3<T>::transpose() const
{
return Matrix3<T>(Vector3<T>(r[0].x, r[1].x, r[2].x),
Vector3<T>(r[0].y, r[1].y, r[2].y),
Vector3<T>(r[0].z, r[1].z, r[2].z));
}
template<class T> T det2x2(T a, T b, T c, T d)
{
return a * d - b * c;
}
template<class T> T Matrix3<T>::determinant() const
{
return (r[0].x * r[1].y * r[2].z +
r[0].y * r[1].z * r[2].x +
r[0].z * r[1].x * r[2].y -
r[0].z * r[1].y * r[2].x -
r[0].x * r[1].z * r[2].y -
r[0].y * r[1].x * r[2].z);
}
template<class T> Matrix3<T> Matrix3<T>::inverse() const
{
Matrix3<T> adjoint;
// Just use Cramer's rule for now . . .
adjoint.r[0].x = det2x2(r[1].y, r[1].z, r[2].y, r[2].z);
adjoint.r[0].y = -det2x2(r[1].x, r[1].z, r[2].x, r[2].z);
adjoint.r[0].z = det2x2(r[1].x, r[1].y, r[2].x, r[2].y);
adjoint.r[1].x = -det2x2(r[0].y, r[0].z, r[2].y, r[2].z);
adjoint.r[1].y = det2x2(r[0].x, r[0].z, r[2].x, r[2].z);
adjoint.r[1].z = -det2x2(r[0].x, r[0].y, r[2].x, r[2].y);
adjoint.r[2].x = det2x2(r[0].y, r[0].z, r[1].y, r[1].z);
adjoint.r[2].y = -det2x2(r[0].x, r[0].z, r[1].x, r[1].z);
adjoint.r[2].z = det2x2(r[0].x, r[0].y, r[1].x, r[1].y);
adjoint *= 1 / determinant();
return adjoint;
}
template<class T> Matrix3<T> Matrix3<T>::xrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix3<T>(Vector3<T>(1, 0, 0),
Vector3<T>(0, c, -s),
Vector3<T>(0, s, c));
}
template<class T> Matrix3<T> Matrix3<T>::yrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix3<T>(Vector3<T>(c, 0, s),
Vector3<T>(0, 1, 0),
Vector3<T>(-s, 0, c));
}
template<class T> Matrix3<T> Matrix3<T>::zrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix3<T>(Vector3<T>(c, -s, 0),
Vector3<T>(s, c, 0),
Vector3<T>(0, 0, 1));
}
/***********************************************
**
** Matrix4 methods
**
***********************************************/
template<class T> Matrix4<T>::Matrix4()
{
r[0] = Vector4<T>(0, 0, 0, 0);
r[1] = Vector4<T>(0, 0, 0, 0);
r[2] = Vector4<T>(0, 0, 0, 0);
r[3] = Vector4<T>(0, 0, 0, 0);
}
template<class T> Matrix4<T>::Matrix4(const Vector4<T>& v0,
const Vector4<T>& v1,
const Vector4<T>& v2,
const Vector4<T>& v3)
{
r[0] = v0;
r[1] = v1;
r[2] = v2;
r[3] = v3;
}
template<class T> const Vector4<T>& Matrix4<T>::operator[](int n) const
{
return r[n];
// return const_cast<Vector4<T>&>(r[n]);
}
template<class T> Vector4<T> Matrix4<T>::row(int n) const
{
return r[n];
}
template<class T> Vector4<T> Matrix4<T>::column(int n) const
{
return Vector4<T>(r[0][n], r[1][n], r[2][n], r[3][n]);
}
template<class T> Matrix4<T> Matrix4<T>::identity()
{
return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
Vector4<T>(0, 1, 0, 0),
Vector4<T>(0, 0, 1, 0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::translation(const Point3<T>& p)
{
return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
Vector4<T>(0, 1, 0, 0),
Vector4<T>(0, 0, 1, 0),
Vector4<T>(p.x, p.y, p.z, 1));
}
template<class T> Matrix4<T> Matrix4<T>::translation(const Vector3<T>& v)
{
return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
Vector4<T>(0, 1, 0, 0),
Vector4<T>(0, 0, 1, 0),
Vector4<T>(v.x, v.y, v.z, 1));
}
template<class T> void Matrix4<T>::translate(const Point3<T>& p)
{
r[3].x += p.x;
r[3].y += p.y;
r[3].z += p.z;
}
template<class T> Matrix4<T> Matrix4<T>::rotation(const Vector3<T>& axis,
T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
T t = 1 - c;
return Matrix4<T>(Vector4<T>(t * axis.x * axis.x + c,
t * axis.x * axis.y - s * axis.z,
t * axis.x * axis.z + s * axis.y,
0),
Vector4<T>(t * axis.x * axis.y + s * axis.z,
t * axis.y * axis.y + c,
t * axis.y * axis.z - s * axis.x,
0),
Vector4<T>(t * axis.x * axis.z - s * axis.y,
t * axis.y * axis.z + s * axis.x,
t * axis.z * axis.z + c,
0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::xrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
Vector4<T>(0, c, -s, 0),
Vector4<T>(0, s, c, 0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::yrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix4<T>(Vector4<T>(c, 0, s, 0),
Vector4<T>(0, 1, 0, 0),
Vector4<T>(-s, 0, c, 0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::zrotation(T angle)
{
T c = (T) cos(angle);
T s = (T) sin(angle);
return Matrix4<T>(Vector4<T>(c, -s, 0, 0),
Vector4<T>(s, c, 0, 0),
Vector4<T>(0, 0, 1, 0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::scaling(const Vector3<T>& scale)
{
return Matrix4<T>(Vector4<T>(scale.x, 0, 0, 0),
Vector4<T>(0, scale.y, 0, 0),
Vector4<T>(0, 0, scale.z, 0),
Vector4<T>(0, 0, 0, 1));
}
template<class T> Matrix4<T> Matrix4<T>::scaling(T scale)
{
return scaling(Vector3<T>(scale, scale, scale));
}
// multiply column vector by a 4x4 matrix
template<class T> Vector3<T> operator*(const Matrix4<T>& m, const Vector3<T>& v)
{
return Vector3<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z,
m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z,
m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z);
}
// multiply row vector by a 4x4 matrix
template<class T> Vector3<T> operator*(const Vector3<T>& v, const Matrix4<T>& m)
{
return Vector3<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z,
m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z,
m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z);
}
// multiply column point by a 4x4 matrix; no projection is performed
template<class T> Point3<T> operator*(const Matrix4<T>& m, const Point3<T>& p)
{
return Point3<T>(m.r[0].x * p.x + m.r[0].y * p.y + m.r[0].z * p.z + m.r[0].w,
m.r[1].x * p.x + m.r[1].y * p.y + m.r[1].z * p.z + m.r[1].w,
m.r[2].x * p.x + m.r[2].y * p.y + m.r[2].z * p.z + m.r[2].w);
}
// multiply row point by a 4x4 matrix; no projection is performed
template<class T> Point3<T> operator*(const Point3<T>& p, const Matrix4<T>& m)
{
return Point3<T>(m.r[0].x * p.x + m.r[1].x * p.y + m.r[2].x * p.z + m.r[3].x,
m.r[0].y * p.x + m.r[1].y * p.y + m.r[2].y * p.z + m.r[3].y,
m.r[0].z * p.x + m.r[1].z * p.y + m.r[2].z * p.z + m.r[3].z);
}
// multiply column vector by a 4x4 matrix
template<class T> Vector4<T> operator*(Matrix4<T>& m, const Vector4<T>& v)
{
return Vector4<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z + m.r[0].w * v.w,
m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z + m.r[1].w * v.w,
m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z + m.r[2].w * v.w,
m.r[3].x * v.x + m.r[3].y * v.y + m.r[3].z * v.z + m.r[3].w * v.w);
}
// multiply row vector by a 4x4 matrix
template<class T> Vector4<T> operator*(const Vector4<T>& v, const Matrix4<T>& m)
{
return Vector4<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z + m.r[3].x * v.w,
m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z + m.r[3].y * v.w,
m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z + m.r[3].z * v.w,
m.r[0].w * v.x + m.r[1].w * v.y + m.r[2].w * v.z + m.r[3].w * v.w);
}
template<class T> Matrix4<T> Matrix4<T>::transpose() const
{
return Matrix4<T>(Vector4<T>(r[0].x, r[1].x, r[2].x, r[3].x),
Vector4<T>(r[0].y, r[1].y, r[2].y, r[3].y),
Vector4<T>(r[0].z, r[1].z, r[2].z, r[3].z),
Vector4<T>(r[0].w, r[1].w, r[2].w, r[3].w));
}
template<class T> Matrix4<T> operator*(const Matrix4<T>& a,
const Matrix4<T>& b)
{
#define MATMUL(R, C) (a[R].x * b[0].C + a[R].y * b[1].C + a[R].z * b[2].C + a[R].w * b[3].C)
return Matrix4<T>(Vector4<T>(MATMUL(0, x), MATMUL(0, y), MATMUL(0, z), MATMUL(0, w)),
Vector4<T>(MATMUL(1, x), MATMUL(1, y), MATMUL(1, z), MATMUL(1, w)),
Vector4<T>(MATMUL(2, x), MATMUL(2, y), MATMUL(2, z), MATMUL(2, w)),
Vector4<T>(MATMUL(3, x), MATMUL(3, y), MATMUL(3, z), MATMUL(3, w)));
#undef MATMUL
}
template<class T> Matrix4<T> operator+(const Matrix4<T>& a, const Matrix4<T>& b)
{
return Matrix4<T>(a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]);
}
#endif // _VECMATH_H_

150
src/visstars.cpp 100644
View File

@ -0,0 +1,150 @@
// visstars.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Keep track of the subset of stars within a database that are visible
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cmath>
#include "celestia.h"
#include "astro.h"
#include "visstars.h"
#include <stdio.h>
// This class walks through the stars in a database to determine which are
// visible to an observer. At worst, we'll go through the entire database
// every time update is called, but if the position of the observer is
// changing slowly enough, this isn't necessary. Instead, we walk through
// only a portion of the database with each update. We flag not only stars
// that are visible, but also stars that might become visible shortly; this
// way, we can limit the effect of the lag due to only checking part of the
// database per update. Two checks are applied to find stars that might
// be visible soon--we look for stars slightly below the limiting magnitude,
// and look for very close stars even if they're well below the limiting
// magnitude. The second check is helpful because very faint stars are
// visible over a much smaller range than bright star, thus a fast-moving
// observer is more likely to miss a faint star.
VisibleStarSet::VisibleStarSet(StarDatabase* db) :
starDB(db),
faintest(6.0f), // average limit of human vision under ideal conditions
closeDistance(0),
firstIndex(0)
{
current = new vector<uint32>;
last = new vector<uint32>;
currentNear = new vector<uint32>;
lastNear = new vector<uint32>;
}
VisibleStarSet::~VisibleStarSet()
{
delete current;
delete last;
delete currentNear;
delete lastNear;
}
// Search through some fraction of the star database and determine
// visibility. By default, search through the entire database.
void VisibleStarSet::update(const Observer& obs, float fraction)
{
uint32 nStars = starDB->size();
uint32 nUpdate = (uint32) (fraction * nStars);
bool willFinish = firstIndex + nUpdate >= nStars;
uint32 endIndex = willFinish ? nStars : firstIndex + nUpdate;
float closeDistance2 = closeDistance * closeDistance;
Point3d obsPositionD = obs.getPosition();
Point3f obsPosition((float) obsPositionD.x,
(float) obsPositionD.y,
(float) obsPositionD.z);
// Compute the irradiance from a star with the minimum apparent
// magnitude. By definition, the apparent magnitude of a star
// viewed from a distance of 10pc is the same as it's absolute
// magnitude, so this is the distance for which we calculate
// irradiance. We omit the factor of 4*pi since it doesn't affect
// comparison of irradiances, which is all we're interested in.
float threshholdLum = astro::absMagToLum(faintest + 0.5f);
float threshholdIrradiance = threshholdLum /
(astro::parsecsToLightYears(10) * astro::parsecsToLightYears(10));
for (uint32 i = firstIndex; i < endIndex; i++)
{
Star* star = starDB->getStar(i);
float dist2 = obsPosition.distanceToSquared(star->getPosition());
// Divisions are costly, so instead of comparing lum/dist2 to
// the threshhold irradiance, we compare lum to threshhold*dist2
if (dist2 < closeDistance2)
{
currentNear->insert(currentNear->end(), i);
current->insert(current->end(), i);
}
else if (star->getLuminosity() >= threshholdIrradiance * dist2)
{
current->insert(current->end(), i);
}
}
if (willFinish)
{
firstIndex = 0;
swap(current, last);
current->clear();
swap(currentNear, lastNear);
currentNear->clear();
}
else
{
firstIndex = endIndex;
}
}
// Search the entire star database for visible stars. This resets
// the results of any previous calls to update. This method is
// appropriate to call to initialize the visible star set or when
// the observer has 'teleported' to a new location.
void VisibleStarSet::updateAll(const Observer& obs)
{
firstIndex = 0;
current->clear();
currentNear->clear();
update(obs, 1);
}
// Get a list of stars currently visible; this list is only valid until the
// next call to update()
vector<uint32>* VisibleStarSet::getVisibleSet() const
{
return last;
}
// Get a list of stars within closeDistance; this list is only valid until the
// next call to update()
vector<uint32>* VisibleStarSet::getCloseSet() const
{
return lastNear;
}
void VisibleStarSet::setLimitingMagnitude(float mag)
{
faintest = mag;
}
void VisibleStarSet::setCloseDistance(float distance)
{
closeDistance = distance;
}

53
src/visstars.h 100644
View File

@ -0,0 +1,53 @@
// visstars.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Keep track of the subset of stars within a database that are visible
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _VISSTARS_H_
#define _VISSTARS_H_
#include <vector>
#include "stardb.h"
#include "observer.h"
using namespace std;
class IntArray
{
};
class VisibleStarSet
{
public:
VisibleStarSet(StarDatabase*);
~VisibleStarSet();
void update(const Observer&, float fraction = 1);
void updateAll(const Observer&);
vector<uint32>* getVisibleSet() const;
vector<uint32>* getCloseSet() const;
void setLimitingMagnitude(float);
void setCloseDistance(float);
private:
VisibleStarSet(VisibleStarSet&) {};
StarDatabase* starDB;
float faintest;
float closeDistance;
vector<uint32>* current;
vector<uint32>* last;
vector<uint32>* currentNear;
vector<uint32>* lastNear;
uint32 firstIndex;
};
#endif // _VISSTARS_H_

1084
src/winmain.cpp 100644

File diff suppressed because it is too large Load Diff