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
commit
b6f1c72ae5
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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");
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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*) ¶ms);
|
||||
}
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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", °Sign, °, &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", ¶llaxError);
|
||||
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);
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_
|
|
@ -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_
|
|
@ -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 *) ¶llax, 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';
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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_
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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();
|
||||
}
|
|
@ -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_
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -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", °Sign, °, &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", ¶llaxError);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 *) ¶llax, sizeof parallax);
|
||||
in.read((char *) &appMag, sizeof appMag);
|
||||
in.read((char *) &stellarClass, sizeof stellarClass);
|
||||
in.read((char *) ¶llaxError, 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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
||||
|
|
@ -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));
|
||||
}
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue