Work on offline generation of data arrays for new planets.
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2767 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
parent
ba30324d99
commit
c8445aeb9e
27
tools/icosmesh/JAIcosMesh.h
Normal file
27
tools/icosmesh/JAIcosMesh.h
Normal file
@ -0,0 +1,27 @@
|
||||
#import "icosmesh.h"
|
||||
|
||||
@class JAVertexSet, JAIcosTriangle;
|
||||
|
||||
|
||||
@interface JAIcosMesh: NSObject
|
||||
{
|
||||
@private
|
||||
JAVertexSet *_vertexSet;
|
||||
NSMutableArray *_indices;
|
||||
NSUInteger _maxIndex;
|
||||
}
|
||||
|
||||
// Vertex set may optionally be specified, so one can be shared between multiple meshes.
|
||||
+ (id) meshWithVertexSet:(JAVertexSet *)vertexSet;
|
||||
- (id) initWithVertexSet:(JAVertexSet *)vertexSet;
|
||||
|
||||
@property (readonly) JAVertexSet *vertexSet;
|
||||
@property (readonly) NSUInteger faceCount;
|
||||
@property (readonly) NSUInteger maxIndex;
|
||||
|
||||
- (void) addTriangle:(JAIcosTriangle *)triangle;
|
||||
- (void) addTriangles:(NSArray *)triangles;
|
||||
|
||||
- (NSArray *) indexArray; // NSArray of faceCount * 3 NSNumbers, being indices into vertexSet.
|
||||
|
||||
@end
|
113
tools/icosmesh/JAIcosMesh.m
Normal file
113
tools/icosmesh/JAIcosMesh.m
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// JAIcosMesh.m
|
||||
// icosmesh
|
||||
//
|
||||
// Created by Jens Ayton on 2009-11-18.
|
||||
// Copyright 2009 Jens Ayton. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JAIcosMesh.h"
|
||||
#import "JAVertexSet.h"
|
||||
#import "JAIcosTriangle.h"
|
||||
|
||||
|
||||
@interface JAIcosMesh ()
|
||||
|
||||
- (void) addOneVertex:(Vertex)v;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation JAIcosMesh
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithVertexSet:nil];
|
||||
}
|
||||
|
||||
|
||||
+ (id) meshWithVertexSet:(JAVertexSet *)vertexSet
|
||||
{
|
||||
return [[[self alloc] initWithVertexSet:vertexSet] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithVertexSet:(JAVertexSet *)vertexSet
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
if (vertexSet == nil) vertexSet = [[[JAVertexSet alloc] init] autorelease];
|
||||
_vertexSet = [vertexSet retain];
|
||||
|
||||
_indices = [[NSMutableArray alloc] init];
|
||||
if (_vertexSet == nil || _indices == nil)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_vertexSet release];
|
||||
[_indices release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (JAVertexSet *)vertexSet
|
||||
{
|
||||
return _vertexSet;
|
||||
}
|
||||
|
||||
|
||||
- (NSUInteger) faceCount
|
||||
{
|
||||
return _indices.count / 3;
|
||||
}
|
||||
|
||||
|
||||
- (NSUInteger) maxIndex
|
||||
{
|
||||
return _maxIndex;
|
||||
}
|
||||
|
||||
|
||||
- (void) addTriangle:(JAIcosTriangle *)triangle
|
||||
{
|
||||
if (triangle == nil) return;
|
||||
|
||||
[self addOneVertex:triangle.vertexA];
|
||||
[self addOneVertex:triangle.vertexB];
|
||||
[self addOneVertex:triangle.vertexC];
|
||||
}
|
||||
|
||||
|
||||
- (void) addTriangles:(NSArray *)triangles
|
||||
{
|
||||
for (JAIcosTriangle *triangle in triangles)
|
||||
{
|
||||
[self addTriangle:triangle];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) indexArray
|
||||
{
|
||||
return [[_indices copy] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (void) addOneVertex:(Vertex)v
|
||||
{
|
||||
NSUInteger index = [_vertexSet indexForVertex:v];
|
||||
[_indices addObject:[NSNumber numberWithUnsignedInteger:index]];
|
||||
if (_maxIndex < index) _maxIndex = index;
|
||||
}
|
||||
|
||||
@end
|
28
tools/icosmesh/JAIcosTriangle.h
Normal file
28
tools/icosmesh/JAIcosTriangle.h
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// JAIcosTriangle.h
|
||||
// icosmesh
|
||||
//
|
||||
// Created by Jens Ayton on 2009-11-18.
|
||||
// Copyright 2009 Jens Ayton. All rights reserved.
|
||||
//
|
||||
|
||||
#import "icosmesh.h"
|
||||
|
||||
|
||||
@interface JAIcosTriangle: NSObject
|
||||
{
|
||||
@private
|
||||
Vertex _vertices[3];
|
||||
}
|
||||
|
||||
// Note: order is not guaranteed to be maintained.
|
||||
+ (id) triangleWithVectorA:(Vector)a b:(Vector)b c:(Vector)c;
|
||||
- (id) initWithVectorA:(Vector)a b:(Vector)b c:(Vector)c;
|
||||
|
||||
- (NSArray *) subdivide; // A list of four JAIcosTriangles.
|
||||
|
||||
@property (readonly) Vertex vertexA;
|
||||
@property (readonly) Vertex vertexB;
|
||||
@property (readonly) Vertex vertexC;
|
||||
|
||||
@end
|
183
tools/icosmesh/JAIcosTriangle.m
Normal file
183
tools/icosmesh/JAIcosTriangle.m
Normal file
@ -0,0 +1,183 @@
|
||||
//
|
||||
// JAIcosTriangle.m
|
||||
// icosmesh
|
||||
//
|
||||
// Created by Jens Ayton on 2009-11-18.
|
||||
// Copyright 2009 Jens Ayton. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JAIcosTriangle.h"
|
||||
|
||||
|
||||
static inline BOOL IsPolarVector(Vector v)
|
||||
{
|
||||
return v.x == 0.0 && v.z == 0.0;
|
||||
}
|
||||
|
||||
|
||||
@interface JAIcosTriangle ()
|
||||
|
||||
- (void) rotate; // a = b, b = c, c = a
|
||||
- (void) generateTextureCoordinates; // Requires that any polar coordinate is in [0].
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static NSComparisonResult CompareVertices(Vertex *a, Vertex *b)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
|
||||
static NSString *VertexDescription(Vertex v)
|
||||
{
|
||||
return [NSString stringWithFormat:@"{ %g, %g, %g} (%g, %g)", v.v.x, v.v.y, v.v.z, v.s, v.t];
|
||||
}
|
||||
|
||||
|
||||
@implementation JAIcosTriangle
|
||||
|
||||
+ (id) triangleWithVectorA:(Vector)a b:(Vector)b c:(Vector)c
|
||||
{
|
||||
return [[[self alloc] initWithVectorA:a b:b c:c] autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (id) initWithVectorA:(Vector)a b:(Vector)b c:(Vector)c
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_vertices[0].v = VectorNormal(a);
|
||||
_vertices[1].v = VectorNormal(b);
|
||||
_vertices[2].v = VectorNormal(c);
|
||||
|
||||
// If one of our vertices is a pole, make it the first.
|
||||
if (IsPolarVector(_vertices[2].v)) [self rotate];
|
||||
if (IsPolarVector(_vertices[1].v)) [self rotate];
|
||||
|
||||
[self generateTextureCoordinates];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat:@"{%@, %@, %@}", VertexDescription(_vertices[0]), VertexDescription(_vertices[1]), VertexDescription(_vertices[2])];
|
||||
}
|
||||
|
||||
|
||||
- (Vertex) vertexA
|
||||
{
|
||||
return _vertices[0];
|
||||
}
|
||||
|
||||
|
||||
- (Vertex) vertexB
|
||||
{
|
||||
return _vertices[1];
|
||||
}
|
||||
|
||||
|
||||
- (Vertex) vertexC
|
||||
{
|
||||
return _vertices[2];
|
||||
}
|
||||
|
||||
|
||||
- (void) rotate
|
||||
{
|
||||
Vertex temp = _vertices[0];
|
||||
_vertices[0] = _vertices[1];
|
||||
_vertices[1] = _vertices[2];
|
||||
_vertices[2] = temp;
|
||||
}
|
||||
|
||||
|
||||
- (void) generateTextureCoordinates
|
||||
{
|
||||
VectorToCoords0_1(_vertices[1].v, &_vertices[1].t, &_vertices[1].s);
|
||||
VectorToCoords0_1(_vertices[2].v, &_vertices[2].t, &_vertices[2].s);
|
||||
if (!IsPolarVector(_vertices[0].v)) VectorToCoords0_1(_vertices[0].v, &_vertices[0].t, &_vertices[0].s);
|
||||
else
|
||||
{
|
||||
// Use longitude of average of v1 and v2.
|
||||
VectorToCoords0_1(VectorAdd(_vertices[1].v, _vertices[2].v), NULL, &_vertices[0].s);
|
||||
_vertices[0].t = (_vertices[0].v.y < 0) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
/* Texture seam handling
|
||||
At the back of the mesh, at the longitude = 180°/-180° meridian, the
|
||||
texture wraps around. However, there isn't a convenient matching seam
|
||||
in the geometry - there are no great circles on a subdivided
|
||||
icosahedron - so we need to adjust texture coordinates and use the
|
||||
GL_REPEAT texture wrapping mode to cover it over.
|
||||
|
||||
The technique is to establish whether we have at least one vertex in
|
||||
each of the (x, -z) and (-x, -z) quadrants, and if so, add 1 to the
|
||||
texture coordinates for the vertices in (-x, -z) -- corresponding to
|
||||
the east Pacific.
|
||||
|
||||
NOTE: this technique is suboptimal because the selection of wrapped
|
||||
vertices changes at each subdivision level. Interpolating texture
|
||||
coordinates during subidivision, then finding the "nearest" option
|
||||
for "correct" calculated s for interpolated vertices could fix this.
|
||||
*/
|
||||
|
||||
bool haveNXNZ = false;
|
||||
bool havePXNZ = false;
|
||||
unsigned i;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vertices[i].v.z < 0)
|
||||
{
|
||||
if (_vertices[i].v.x <= 0)
|
||||
{
|
||||
haveNXNZ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
havePXNZ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (haveNXNZ && havePXNZ)
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vertices[i].v.z < 0 && _vertices[i].v.x >= 0)
|
||||
{
|
||||
printf("Remapping %g -> %g\n", _vertices[i].s, _vertices[i].s + 1.0);
|
||||
_vertices[i].s += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) subdivide
|
||||
{
|
||||
Vector a = _vertices[0].v;
|
||||
Vector b = _vertices[1].v;
|
||||
Vector c = _vertices[2].v;
|
||||
|
||||
Vector ab = VectorNormal(VectorAdd(a, b));
|
||||
Vector bc = VectorNormal(VectorAdd(b, c));
|
||||
Vector ca = VectorNormal(VectorAdd(c, a));
|
||||
|
||||
/* Note: vertex orders preserve winding. Triangle order is intended to be
|
||||
somewhat cache-friendly, but not as good as actually optimizing the
|
||||
data.
|
||||
*/
|
||||
JAIcosTriangle *subTris[4];
|
||||
subTris[0] = [JAIcosTriangle triangleWithVectorA:a b:ab c:ca];
|
||||
subTris[3] = [JAIcosTriangle triangleWithVectorA:ab b:bc c:ca];
|
||||
subTris[1] = [JAIcosTriangle triangleWithVectorA:ab b:b c:bc];
|
||||
subTris[2] = [JAIcosTriangle triangleWithVectorA:ca b:bc c:c];
|
||||
|
||||
return [NSArray arrayWithObjects:subTris count:4];
|
||||
}
|
||||
|
||||
@end
|
19
tools/icosmesh/JAVertexSet.h
Normal file
19
tools/icosmesh/JAVertexSet.h
Normal file
@ -0,0 +1,19 @@
|
||||
#import "icosmesh.h"
|
||||
|
||||
|
||||
@interface JAVertexSet: NSObject
|
||||
{
|
||||
@private
|
||||
NSMutableDictionary *_indices;
|
||||
NSMutableArray *_vertices;
|
||||
}
|
||||
|
||||
- (NSUInteger) indexForVertex:(Vertex)vertex;
|
||||
- (Vertex) vertexAtIndex:(NSUInteger)index;
|
||||
|
||||
@property (readonly) NSUInteger count;
|
||||
|
||||
- (NSArray *) positionArray; // Array of 3 * count numbers representing vertex positions
|
||||
- (NSArray *) texCoordArray; // Array of 2 * count numbers representing texture coordinates
|
||||
|
||||
@end
|
95
tools/icosmesh/JAVertexSet.m
Normal file
95
tools/icosmesh/JAVertexSet.m
Normal file
@ -0,0 +1,95 @@
|
||||
#import "JAVertexSet.h"
|
||||
|
||||
|
||||
@implementation JAVertexSet
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_indices = [[NSMutableDictionary alloc] init];
|
||||
_vertices = [[NSMutableArray alloc] init];
|
||||
|
||||
if (_indices == NULL || _vertices == NULL)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_indices release];
|
||||
[_vertices release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSUInteger) indexForVertex:(Vertex)vertex
|
||||
{
|
||||
NSValue *value = [NSValue value:&vertex withObjCType:@encode(Vertex)];
|
||||
NSNumber *number = [_indices objectForKey:value];
|
||||
if (number == nil)
|
||||
{
|
||||
number = [NSNumber numberWithUnsignedInteger:self.count];
|
||||
[_indices setObject:number forKey:value];
|
||||
[_vertices addObject:value];
|
||||
}
|
||||
|
||||
return [number unsignedIntegerValue];
|
||||
}
|
||||
|
||||
|
||||
- (Vertex) vertexAtIndex:(NSUInteger)index
|
||||
{
|
||||
if (index >= self.count)
|
||||
{
|
||||
[NSException raise:NSRangeException format:@"%s: attempt to access element %u of %u", __FUNCTION__, index, self.count];
|
||||
}
|
||||
|
||||
Vertex result;
|
||||
[[_vertices objectAtIndex:index] getValue:&result];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (NSUInteger) count
|
||||
{
|
||||
return _vertices.count;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) positionArray
|
||||
{
|
||||
unsigned i, count = self.count;
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:count * 3];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Vertex v = [self vertexAtIndex:i];
|
||||
[result addObject:[NSNumber numberWithDouble:v.v.x]];
|
||||
[result addObject:[NSNumber numberWithDouble:v.v.y]];
|
||||
[result addObject:[NSNumber numberWithDouble:v.v.z]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) texCoordArray
|
||||
{
|
||||
unsigned i, count = self.count;
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:count * 2];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Vertex v = [self vertexAtIndex:i];
|
||||
[result addObject:[NSNumber numberWithDouble:v.s]];
|
||||
[result addObject:[NSNumber numberWithDouble:v.t]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
2
tools/icosmesh/OOOpenGL.h
Normal file
2
tools/icosmesh/OOOpenGL.h
Normal file
@ -0,0 +1,2 @@
|
||||
typedef float GLfloat;
|
||||
typedef unsigned GLuint;
|
111
tools/icosmesh/OOPlanetData_template.c
Normal file
111
tools/icosmesh/OOPlanetData_template.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
OOPlanetData.c
|
||||
For Oolite
|
||||
|
||||
This file was automatically generated by tools/icosmesh. Do not modify.
|
||||
|
||||
This data may be used freely.
|
||||
*/
|
||||
|
||||
#include "OOPlanetData.h"
|
||||
|
||||
|
||||
static const GLfloat kLevel0Vertices[60] =
|
||||
{
|
||||
+0.00000000f, +1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.89442718f, +0.44721359f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.27639320f, +0.44721359f, +0.85065079f /* Magnitude: 1 */,
|
||||
-0.72360682f, +0.44721359f, +0.52573115f /* Magnitude: 1 */,
|
||||
-0.72360682f, +0.44721359f, -0.52573115f /* Magnitude: 1 */,
|
||||
+0.27639320f, +0.44721359f, -0.85065079f /* Magnitude: 1 */,
|
||||
+0.72360682f, -0.44721359f, +0.52573115f /* Magnitude: 1 */,
|
||||
-0.27639320f, -0.44721359f, +0.85065079f /* Magnitude: 1 */,
|
||||
-0.89442718f, -0.44721359f, +0.00000000f /* Magnitude: 1 */,
|
||||
-0.27639320f, -0.44721359f, -0.85065079f /* Magnitude: 1 */,
|
||||
+0.72360682f, -0.44721359f, -0.52573115f /* Magnitude: 1 */,
|
||||
+0.00000000f, -1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, +1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, +1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, +1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, +1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, -1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, -1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, -1.00000000f, +0.00000000f /* Magnitude: 1 */,
|
||||
+0.00000000f, -1.00000000f, +0.00000000f /* Magnitude: 1 */
|
||||
};
|
||||
|
||||
static const GLfloat kLevel0TexCoords[40] =
|
||||
{
|
||||
+0.25000000f, +0.00000000f,
|
||||
+0.25000000f, +0.35241637f,
|
||||
+0.05000000f, +0.35241637f,
|
||||
+0.84999996f, +0.35241640f,
|
||||
+0.65000004f, +0.35241640f,
|
||||
+0.44999999f, +0.35241637f,
|
||||
+0.15000001f, +0.64758360f,
|
||||
+0.94999999f, +0.64758360f,
|
||||
+0.75000000f, +0.64758360f,
|
||||
+0.55000001f, +0.64758360f,
|
||||
+0.34999999f, +0.64758360f,
|
||||
+0.50000000f, +1.00000000f,
|
||||
+0.25000000f, +0.00000000f,
|
||||
+0.25000000f, +0.00000000f,
|
||||
+0.25000000f, +0.00000000f,
|
||||
+0.25000000f, +0.00000000f,
|
||||
+0.50000000f, +1.00000000f,
|
||||
+0.50000000f, +1.00000000f,
|
||||
+0.50000000f, +1.00000000f,
|
||||
+0.50000000f, +1.00000000f
|
||||
};
|
||||
|
||||
static const GLuint kLevel0Indices[60] =
|
||||
{
|
||||
0, 1, 2,
|
||||
12, 2, 3,
|
||||
13, 3, 4,
|
||||
14, 4, 5,
|
||||
15, 5, 1,
|
||||
11, 6, 7,
|
||||
16, 7, 8,
|
||||
17, 8, 9,
|
||||
18, 9, 10,
|
||||
19, 10, 6,
|
||||
1, 2, 6,
|
||||
2, 3, 7,
|
||||
3, 4, 8,
|
||||
4, 5, 9,
|
||||
5, 1, 10,
|
||||
6, 7, 2,
|
||||
7, 8, 3,
|
||||
8, 9, 4,
|
||||
9, 10, 5,
|
||||
10, 6, 1
|
||||
};
|
||||
|
||||
|
||||
#define kLevel1Vertices 0
|
||||
#define kLevel1TexCoords 0
|
||||
#define kLevel1Indices 0
|
||||
#define kLevel2Vertices 0
|
||||
#define kLevel2TexCoords 0
|
||||
#define kLevel2Indices 0
|
||||
#define kLevel3Vertices 0
|
||||
#define kLevel3TexCoords 0
|
||||
#define kLevel3Indices 0
|
||||
#define kLevel4Vertices 0
|
||||
#define kLevel4TexCoords 0
|
||||
#define kLevel4Indices 0
|
||||
#define kLevel5Vertices 0
|
||||
#define kLevel5TexCoords 0
|
||||
#define kLevel5Indices 0
|
||||
|
||||
|
||||
const OOPlanetDataLevel kPlanetData[kOOPlanetDataLevels] =
|
||||
{
|
||||
{ 20, 20, kLevel0Vertices, kLevel0Indices, kLevel0TexCoords },
|
||||
{ 20, 20, kLevel1Vertices, kLevel1Indices, kLevel1TexCoords },
|
||||
{ 20, 20, kLevel2Vertices, kLevel2Indices, kLevel2TexCoords },
|
||||
{ 20, 20, kLevel3Vertices, kLevel3Indices, kLevel3TexCoords },
|
||||
{ 20, 20, kLevel4Vertices, kLevel4Indices, kLevel4TexCoords },
|
||||
{ 20, 20, kLevel5Vertices, kLevel5Indices, kLevel5TexCoords }
|
||||
};
|
26
tools/icosmesh/OOPlanetData_template.h
Normal file
26
tools/icosmesh/OOPlanetData_template.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
OOPlanetData.h
|
||||
For Oolite
|
||||
|
||||
This file was automatically generated by tools/icosmesh. Do not modify.
|
||||
|
||||
This data may be used freely.
|
||||
*/
|
||||
|
||||
#import "OOOpenGL.h"
|
||||
|
||||
|
||||
#define kOOPlanetDataLevels 6
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned vertexCount;
|
||||
unsigned faceCount;
|
||||
const GLfloat *vertices; // vertexCount * 3
|
||||
const GLuint *indices; // faceCount * 3
|
||||
const GLfloat *texCoords; // vertexCount * 2
|
||||
} OOPlanetDataLevel;
|
||||
|
||||
|
||||
extern const OOPlanetDataLevel kPlanetData[kOOPlanetDataLevels];
|
74
tools/icosmesh/generatemesh.c
Normal file
74
tools/icosmesh/generatemesh.c
Normal file
@ -0,0 +1,74 @@
|
||||
#import "OOPlanetData.h"
|
||||
#import "OOMaths.h"
|
||||
#import <stdio.h>
|
||||
#import <assert.h>
|
||||
|
||||
#define kScale 500
|
||||
|
||||
|
||||
static Vector GetVector(GLuint idx)
|
||||
{
|
||||
return make_vector(kOOPlanetVertices[idx * 3], kOOPlanetVertices[idx * 3 + 1], kOOPlanetVertices[idx * 3 + 2]);
|
||||
}
|
||||
|
||||
|
||||
static void WriteDAT(unsigned i);
|
||||
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < kOOPlanetDataLevels; i++)
|
||||
{
|
||||
WriteDAT(i);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void WriteDAT(unsigned level)
|
||||
{
|
||||
const OOPlanetDataLevel *data = &kPlanetData[level];
|
||||
|
||||
char name[20];
|
||||
snprintf(name, 20, "level_%u.dat", level);
|
||||
FILE *file = fopen(name, "w");
|
||||
|
||||
fprintf(file, "NVERTS %u\nNFACES %u\n\nVERTEX\n", data->vertexCount, data->faceCount);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < data->vertexCount; i++)
|
||||
{
|
||||
fprintf(file, "%g, %g, %g\n", kOOPlanetVertices[i * 3] * kScale, kOOPlanetVertices[i * 3 + 1] * kScale, kOOPlanetVertices[i * 3 + 2] * kScale);
|
||||
}
|
||||
|
||||
fprintf(file, "\nFACES\n");
|
||||
for (i = 0; i < data->faceCount; i++)
|
||||
{
|
||||
GLuint a = data->indices[i * 3];
|
||||
GLuint b = data->indices[i * 3 + 1];
|
||||
GLuint c = data->indices[i * 3 + 2];
|
||||
|
||||
Vector va = GetVector(a);
|
||||
Vector vb = GetVector(b);
|
||||
Vector vc = GetVector(c);
|
||||
Vector n = vector_normal(vector_add(va, vector_add(vb, vc)));
|
||||
|
||||
fprintf(file, "1,0,0, %g,%g,%g, 3, %u,%u,%u\n", n.x, n.y, n.z, a, b, c);
|
||||
}
|
||||
|
||||
fprintf(file, "\nTEXTURES\n");
|
||||
for (i = 0; i < data->faceCount; i++)
|
||||
{
|
||||
GLuint a = data->indices[i * 3];
|
||||
GLuint b = data->indices[i * 3 + 1];
|
||||
GLuint c = data->indices[i * 3 + 2];
|
||||
|
||||
fprintf(file, "world.png 1 1 %g %g %g %g %g %g\n", kOOPlanetTexCoords[a * 2], kOOPlanetTexCoords[a * 2 + 1], kOOPlanetTexCoords[b * 2], kOOPlanetTexCoords[b * 2 + 1], kOOPlanetTexCoords[c * 2], kOOPlanetTexCoords[c * 2 + 1]);
|
||||
}
|
||||
|
||||
fprintf(file, "\nEND\n");
|
||||
fclose(file);
|
||||
}
|
||||
|
63
tools/icosmesh/icosmesh.h
Normal file
63
tools/icosmesh/icosmesh.h
Normal file
@ -0,0 +1,63 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <math.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double x, y, z;
|
||||
} Vector;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vector v;
|
||||
double s, t; // Lat/long texture coordinates
|
||||
} Vertex;
|
||||
|
||||
|
||||
|
||||
// Convert vector to latitude and longitude (or θ and φ).
|
||||
void VectorToCoordsRad(Vector vc, double *latitude, double *longitude);
|
||||
void VectorToCoords0_1(Vector vc, double *latitude, double *longitude);
|
||||
|
||||
|
||||
static inline Vector VectorAdd(Vector u, Vector v)
|
||||
{
|
||||
return (Vector){ u.x + v.x, u.y + v.y, u.z + v.z };
|
||||
}
|
||||
|
||||
|
||||
static inline Vector VectorSubtract(Vector u, Vector v)
|
||||
{
|
||||
return (Vector){ u.x - v.x, u.y - v.y, u.z - v.z };
|
||||
}
|
||||
|
||||
|
||||
static inline double VectorDot(Vector u, Vector v)
|
||||
{
|
||||
return u.x * v.x + u.y * v.y + u.z * v.z;
|
||||
}
|
||||
|
||||
|
||||
static inline double VectorMagnitude(Vector v)
|
||||
{
|
||||
return sqrt(VectorDot(v, v));
|
||||
}
|
||||
|
||||
|
||||
static inline Vector VectorScale(Vector v, double s)
|
||||
{
|
||||
return (Vector){ v.x * s, v.y * s, v.z * s };
|
||||
}
|
||||
|
||||
|
||||
static inline Vector VectorScaleReciprocal(Vector v, double s)
|
||||
{
|
||||
return (Vector){ v.x / s, v.y / s, v.z / s };
|
||||
}
|
||||
|
||||
|
||||
static inline Vector VectorNormal(Vector v)
|
||||
{
|
||||
return VectorScaleReciprocal(v, VectorMagnitude(v));
|
||||
}
|
376
tools/icosmesh/icosmesh.xcodeproj/project.pbxproj
Normal file
376
tools/icosmesh/icosmesh.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,376 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 45;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1A675E6D10B4528F00786F5F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A675E6C10B4528F00786F5F /* Foundation.framework */; };
|
||||
1A675ED710B456F200786F5F /* OOFastArithmetic.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED010B456EB00786F5F /* OOFastArithmetic.m */; };
|
||||
1A675ED810B456F300786F5F /* OOMatrix.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED210B456EB00786F5F /* OOMatrix.m */; };
|
||||
1A675ED910B456F300786F5F /* OOQuaternion.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED410B456EB00786F5F /* OOQuaternion.m */; };
|
||||
1A675EDA10B456F300786F5F /* OOVector.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED610B456EB00786F5F /* OOVector.m */; };
|
||||
1A675F6210B466AF00786F5F /* generatemesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A675F6110B466AF00786F5F /* generatemesh.c */; };
|
||||
1A675F6810B466CE00786F5F /* OOPlanetData.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A675F6610B466CE00786F5F /* OOPlanetData.c */; };
|
||||
1A675FC710B4710E00786F5F /* OOFastArithmetic.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED010B456EB00786F5F /* OOFastArithmetic.m */; };
|
||||
1A675FC810B4710F00786F5F /* OOMatrix.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED210B456EB00786F5F /* OOMatrix.m */; };
|
||||
1A675FC910B4710F00786F5F /* OOQuaternion.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED410B456EB00786F5F /* OOQuaternion.m */; };
|
||||
1A675FCA10B4711000786F5F /* OOVector.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A675ED610B456EB00786F5F /* OOVector.m */; };
|
||||
1A67607310B486EE00786F5F /* JAIcosTriangle.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A67605510B479D200786F5F /* JAIcosTriangle.m */; };
|
||||
1A6760A710B48EC000786F5F /* JAIcosMesh.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A67609610B48C6600786F5F /* JAIcosMesh.m */; };
|
||||
1A6760A810B48EC200786F5F /* JAVertexSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A67608F10B4897B00786F5F /* JAVertexSet.m */; };
|
||||
8DD76F770486A8DE00D96B5E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.m */; settings = {ATTRIBUTES = (); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1A675F6A10B466F700786F5F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8DD76F740486A8DE00D96B5E;
|
||||
remoteInfo = icosmesh;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8DD76F7B0486A8DE00D96B5E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 8;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
|
||||
1A675E6C10B4528F00786F5F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
1A675ECD10B456EB00786F5F /* OOMaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOMaths.h; sourceTree = "<group>"; };
|
||||
1A675ECE10B456EB00786F5F /* OOFunctionAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOFunctionAttributes.h; sourceTree = "<group>"; };
|
||||
1A675ECF10B456EB00786F5F /* OOFastArithmetic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOFastArithmetic.h; sourceTree = "<group>"; };
|
||||
1A675ED010B456EB00786F5F /* OOFastArithmetic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOFastArithmetic.m; sourceTree = "<group>"; };
|
||||
1A675ED110B456EB00786F5F /* OOMatrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOMatrix.h; sourceTree = "<group>"; };
|
||||
1A675ED210B456EB00786F5F /* OOMatrix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOMatrix.m; sourceTree = "<group>"; };
|
||||
1A675ED310B456EB00786F5F /* OOQuaternion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOQuaternion.h; sourceTree = "<group>"; };
|
||||
1A675ED410B456EB00786F5F /* OOQuaternion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOQuaternion.m; sourceTree = "<group>"; };
|
||||
1A675ED510B456EB00786F5F /* OOVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOVector.h; sourceTree = "<group>"; };
|
||||
1A675ED610B456EB00786F5F /* OOVector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOVector.m; sourceTree = "<group>"; };
|
||||
1A675F5D10B466A000786F5F /* generatemesh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generatemesh; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1A675F6110B466AF00786F5F /* generatemesh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = generatemesh.c; sourceTree = "<group>"; };
|
||||
1A675F6610B466CE00786F5F /* OOPlanetData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OOPlanetData.c; path = build/Debug/OOPlanetData.c; sourceTree = "<group>"; };
|
||||
1A675F6710B466CE00786F5F /* OOPlanetData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OOPlanetData.h; path = build/Debug/OOPlanetData.h; sourceTree = "<group>"; };
|
||||
1A675F7610B4684900786F5F /* OOOpenGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOOpenGL.h; sourceTree = "<group>"; };
|
||||
1A67605410B479D200786F5F /* JAIcosTriangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JAIcosTriangle.h; sourceTree = "<group>"; };
|
||||
1A67605510B479D200786F5F /* JAIcosTriangle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JAIcosTriangle.m; sourceTree = "<group>"; };
|
||||
1A67605710B479EA00786F5F /* icosmesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icosmesh.h; sourceTree = "<group>"; };
|
||||
1A67608E10B4897B00786F5F /* JAVertexSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JAVertexSet.h; sourceTree = "<group>"; };
|
||||
1A67608F10B4897B00786F5F /* JAVertexSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JAVertexSet.m; sourceTree = "<group>"; };
|
||||
1A67609510B48C6600786F5F /* JAIcosMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JAIcosMesh.h; sourceTree = "<group>"; };
|
||||
1A67609610B48C6600786F5F /* JAIcosMesh.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JAIcosMesh.m; sourceTree = "<group>"; };
|
||||
8DD76F7E0486A8DE00D96B5E /* icosmesh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = icosmesh; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
1A675F5B10B466A000786F5F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8DD76F780486A8DE00D96B5E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1A675E6D10B4528F00786F5F /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08FB7794FE84155DC02AAC07 /* icosmesh */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB7795FE84155DC02AAC07 /* Source */,
|
||||
1A675ECC10B456EB00786F5F /* OOMaths */,
|
||||
1A675F6110B466AF00786F5F /* generatemesh.c */,
|
||||
1A2A9BB010B6CBEB0039208A /* New Group */,
|
||||
1A675F6410B466BB00786F5F /* Generated files */,
|
||||
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
|
||||
19C28FBDFE9D53C911CA2CBB /* Products */,
|
||||
1A675E6C10B4528F00786F5F /* Foundation.framework */,
|
||||
);
|
||||
name = icosmesh;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB7795FE84155DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB7796FE84155DC02AAC07 /* main.m */,
|
||||
1A67605710B479EA00786F5F /* icosmesh.h */,
|
||||
1A675F7610B4684900786F5F /* OOOpenGL.h */,
|
||||
1A67605410B479D200786F5F /* JAIcosTriangle.h */,
|
||||
1A67605510B479D200786F5F /* JAIcosTriangle.m */,
|
||||
1A67608E10B4897B00786F5F /* JAVertexSet.h */,
|
||||
1A67608F10B4897B00786F5F /* JAVertexSet.m */,
|
||||
1A67609510B48C6600786F5F /* JAIcosMesh.h */,
|
||||
1A67609610B48C6600786F5F /* JAIcosMesh.m */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */,
|
||||
);
|
||||
name = "External Frameworks and Libraries";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
19C28FBDFE9D53C911CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8DD76F7E0486A8DE00D96B5E /* icosmesh */,
|
||||
1A675F5D10B466A000786F5F /* generatemesh */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A2A9BB010B6CBEB0039208A /* New Group */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = "New Group";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A675ECC10B456EB00786F5F /* OOMaths */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1A675ECD10B456EB00786F5F /* OOMaths.h */,
|
||||
1A675ECE10B456EB00786F5F /* OOFunctionAttributes.h */,
|
||||
1A675ECF10B456EB00786F5F /* OOFastArithmetic.h */,
|
||||
1A675ED010B456EB00786F5F /* OOFastArithmetic.m */,
|
||||
1A675ED110B456EB00786F5F /* OOMatrix.h */,
|
||||
1A675ED210B456EB00786F5F /* OOMatrix.m */,
|
||||
1A675ED310B456EB00786F5F /* OOQuaternion.h */,
|
||||
1A675ED410B456EB00786F5F /* OOQuaternion.m */,
|
||||
1A675ED510B456EB00786F5F /* OOVector.h */,
|
||||
1A675ED610B456EB00786F5F /* OOVector.m */,
|
||||
);
|
||||
name = OOMaths;
|
||||
path = ../../src/Core;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
1A675F6410B466BB00786F5F /* Generated files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1A675F6710B466CE00786F5F /* OOPlanetData.h */,
|
||||
1A675F6610B466CE00786F5F /* OOPlanetData.c */,
|
||||
);
|
||||
name = "Generated files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
1A675F5C10B466A000786F5F /* generatemesh */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1A675F6310B466B000786F5F /* Build configuration list for PBXNativeTarget "generatemesh" */;
|
||||
buildPhases = (
|
||||
1A675F6E10B466FF00786F5F /* ShellScript */,
|
||||
1A675F5A10B466A000786F5F /* Sources */,
|
||||
1A675F5B10B466A000786F5F /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
1A675F6B10B466F700786F5F /* PBXTargetDependency */,
|
||||
);
|
||||
name = generatemesh;
|
||||
productName = generatemesh;
|
||||
productReference = 1A675F5D10B466A000786F5F /* generatemesh */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
8DD76F740486A8DE00D96B5E /* icosmesh */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1DEB924708733DCA0010E9CD /* Build configuration list for PBXNativeTarget "icosmesh" */;
|
||||
buildPhases = (
|
||||
8DD76F760486A8DE00D96B5E /* Sources */,
|
||||
8DD76F780486A8DE00D96B5E /* Frameworks */,
|
||||
8DD76F7B0486A8DE00D96B5E /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = icosmesh;
|
||||
productInstallPath = "$(HOME)/bin";
|
||||
productName = icosmesh;
|
||||
productReference = 8DD76F7E0486A8DE00D96B5E /* icosmesh */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
};
|
||||
buildConfigurationList = 1DEB924B08733DCA0010E9CD /* Build configuration list for PBXProject "icosmesh" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* icosmesh */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8DD76F740486A8DE00D96B5E /* icosmesh */,
|
||||
1A675F5C10B466A000786F5F /* generatemesh */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
1A675F6E10B466FF00786F5F /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "cd \"$BUILT_PRODUCTS_DIR\"\n\"$BUILT_PRODUCTS_DIR/icosmesh\"\n\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
1A675F5A10B466A000786F5F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1A675F6210B466AF00786F5F /* generatemesh.c in Sources */,
|
||||
1A675F6810B466CE00786F5F /* OOPlanetData.c in Sources */,
|
||||
1A675FC710B4710E00786F5F /* OOFastArithmetic.m in Sources */,
|
||||
1A675FC810B4710F00786F5F /* OOMatrix.m in Sources */,
|
||||
1A675FC910B4710F00786F5F /* OOQuaternion.m in Sources */,
|
||||
1A675FCA10B4711000786F5F /* OOVector.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8DD76F760486A8DE00D96B5E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8DD76F770486A8DE00D96B5E /* main.m in Sources */,
|
||||
1A675ED710B456F200786F5F /* OOFastArithmetic.m in Sources */,
|
||||
1A675ED810B456F300786F5F /* OOMatrix.m in Sources */,
|
||||
1A675ED910B456F300786F5F /* OOQuaternion.m in Sources */,
|
||||
1A675EDA10B456F300786F5F /* OOVector.m in Sources */,
|
||||
1A67607310B486EE00786F5F /* JAIcosTriangle.m in Sources */,
|
||||
1A6760A710B48EC000786F5F /* JAIcosMesh.m in Sources */,
|
||||
1A6760A810B48EC200786F5F /* JAVertexSet.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
1A675F6B10B466F700786F5F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 8DD76F740486A8DE00D96B5E /* icosmesh */;
|
||||
targetProxy = 1A675F6A10B466F700786F5F /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1A675F5F10B466A100786F5F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "OOMATHS_STANDALONE=1";
|
||||
INSTALL_PATH = /usr/local/bin;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
Foundation,
|
||||
"-framework",
|
||||
AppKit,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
PRODUCT_NAME = generatemesh;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB924808733DCA0010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "OOMATHS_STANDALONE=1";
|
||||
INSTALL_PATH = /usr/local/bin;
|
||||
PRODUCT_NAME = icosmesh;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB924C08733DCA0010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.6;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1A675F6310B466B000786F5F /* Build configuration list for PBXNativeTarget "generatemesh" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1A675F5F10B466A100786F5F /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
};
|
||||
1DEB924708733DCA0010E9CD /* Build configuration list for PBXNativeTarget "icosmesh" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB924808733DCA0010E9CD /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
};
|
||||
1DEB924B08733DCA0010E9CD /* Build configuration list for PBXProject "icosmesh" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB924C08733DCA0010E9CD /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
}
|
289
tools/icosmesh/main.m
Normal file
289
tools/icosmesh/main.m
Normal file
@ -0,0 +1,289 @@
|
||||
/* icosmesh
|
||||
|
||||
Tool to generate subdivided icosahedron mesh data.
|
||||
*/
|
||||
|
||||
#import <stdio.h>
|
||||
#import "icosmesh.h"
|
||||
#import "JAIcosTriangle.h"
|
||||
#import "JAVertexSet.h"
|
||||
#import "JAIcosMesh.h"
|
||||
|
||||
|
||||
#define kFileName "OOPlanetData"
|
||||
|
||||
#define kLevels 6
|
||||
|
||||
|
||||
/* Coordinates of icosahedron with poles on the Y axis.
|
||||
Based on http://www.csee.umbc.edu/~squire/reference/polyhedra.shtml#icosahedron
|
||||
*/
|
||||
static const Vector kBaseVertices[12] =
|
||||
{
|
||||
{ +0.000000000000, +1.000000000000, +0.000000000000 },
|
||||
{ +0.894427200187, +0.447213577125, +0.000000000000 },
|
||||
{ +0.276393205089, +0.447213577125, +0.850650817090 },
|
||||
{ -0.723606805183, +0.447213577125, +0.525731117519 },
|
||||
{ -0.723606805183, +0.447213577125, -0.525731117519 },
|
||||
{ +0.276393205089, +0.447213577125, -0.850650817090 },
|
||||
{ +0.723606805183, -0.447213577125, +0.525731117519 },
|
||||
{ -0.276393205089, -0.447213577125, +0.850650817090 },
|
||||
{ -0.894427200187, -0.447213577125, +0.000000000000 },
|
||||
{ -0.276393205089, -0.447213577125, -0.850650817090 },
|
||||
{ +0.723606805183, -0.447213577125, -0.525731117519 },
|
||||
{ +0.000000000000, -1.000000000000, +0.000000000000 }
|
||||
};
|
||||
|
||||
|
||||
#define kBaseFaceCount 20
|
||||
static const struct { unsigned a, b, c; } kBaseTriangles[kBaseFaceCount] =
|
||||
{
|
||||
{ 0, 1, 2 },
|
||||
{ 0, 2, 3 },
|
||||
{ 0, 3, 4 },
|
||||
{ 0, 4, 5 },
|
||||
{ 0, 5, 1 },
|
||||
{ 11, 6, 7 },
|
||||
{ 11, 7, 8 },
|
||||
{ 11, 8, 9 },
|
||||
{ 11, 9, 10 },
|
||||
{ 11, 10, 6 },
|
||||
{ 1, 2, 6 },
|
||||
{ 2, 3, 7 },
|
||||
{ 3, 4, 8 },
|
||||
{ 4, 5, 9 },
|
||||
{ 5, 1, 10 },
|
||||
{ 6, 7, 2 },
|
||||
{ 7, 8, 3 },
|
||||
{ 8, 9, 4 },
|
||||
{ 9, 10, 5 },
|
||||
{ 10, 6, 1 }
|
||||
};
|
||||
|
||||
|
||||
static NSArray *SubdivideMesh(NSArray *triangles);
|
||||
|
||||
static void WritePrelude(FILE *header, FILE *source);
|
||||
static void WriteVertices(FILE *header, FILE *source, JAVertexSet *vertices);
|
||||
static void WriteMeshForTriangles(FILE *source, unsigned level, NSArray *triangles, JAVertexSet *vertices, unsigned *faceCount, unsigned *maxVertex);
|
||||
static void WriteMesh(FILE *source, unsigned level, JAIcosMesh *mesh);
|
||||
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
|
||||
FILE *header = fopen(kFileName ".h", "w");
|
||||
FILE *source = fopen(kFileName ".c", "w");
|
||||
if (header == NULL || source == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to open output files.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
WritePrelude(header, source);
|
||||
|
||||
// Load up the base triangles.
|
||||
unsigned i;
|
||||
NSMutableArray *baseTriangles = [NSMutableArray arrayWithCapacity:kBaseFaceCount];
|
||||
for (i = 0; i < kBaseFaceCount; i++)
|
||||
{
|
||||
Vector a = kBaseVertices[kBaseTriangles[i].a];
|
||||
Vector b = kBaseVertices[kBaseTriangles[i].b];
|
||||
Vector c = kBaseVertices[kBaseTriangles[i].c];
|
||||
|
||||
// printf("%g %g %g %g %g %g %g %g %g\n", a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z);
|
||||
|
||||
JAIcosTriangle *tri = [JAIcosTriangle triangleWithVectorA:a b:b c:c];
|
||||
[baseTriangles addObject:tri];
|
||||
}
|
||||
|
||||
unsigned faceCount[kLevels];
|
||||
unsigned maxIndex[kLevels];
|
||||
JAVertexSet *vertices = [[[JAVertexSet alloc] init] autorelease];
|
||||
WriteMeshForTriangles(source, 0, baseTriangles, vertices, &faceCount[0], &maxIndex[0]);
|
||||
NSArray *triangles = baseTriangles;
|
||||
|
||||
for (i = 1; i < kLevels; i++)
|
||||
{
|
||||
triangles = (NSMutableArray *)SubdivideMesh(triangles);
|
||||
WriteMeshForTriangles(source, i, triangles, vertices, &faceCount[i], &maxIndex[i]);
|
||||
}
|
||||
|
||||
WriteVertices(header, source, vertices);
|
||||
|
||||
fprintf(source, "\n\nconst OOPlanetDataLevel kPlanetData[kOOPlanetDataLevels] =\n{\n");
|
||||
for (i = 0; i < kLevels; i++)
|
||||
{
|
||||
if (i != 0) fprintf(source, ",\n");
|
||||
fprintf(source, "\t%u, %u, kFaceIndicesLevel%u", maxIndex[i], faceCount[i], i);
|
||||
}
|
||||
fprintf(source, "\n};\n");
|
||||
|
||||
fclose(header);
|
||||
fclose(source);
|
||||
|
||||
[pool release];
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NSArray *SubdivideMesh(NSArray *triangles)
|
||||
{
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:triangles.count * 4];
|
||||
|
||||
for (JAIcosTriangle *triangle in triangles)
|
||||
{
|
||||
[result addObjectsFromArray:[triangle subdivide]];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void WritePrelude(FILE *header, FILE *source)
|
||||
{
|
||||
fprintf(header,
|
||||
"/*\n"
|
||||
"\t%s.h\n"
|
||||
"\tFor Oolite\n"
|
||||
"\t\n"
|
||||
"\tThis file was automatically generated by tools/icosmesh. Do not modify.\n"
|
||||
"\t\n"
|
||||
"\tThis data may be used freely.\n"
|
||||
"*/\n"
|
||||
"\n"
|
||||
"#import \"OOOpenGL.h\"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define kOOPlanetDataLevels %u\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
"\tunsigned vertexCount;\n"
|
||||
"\tunsigned faceCount;\n"
|
||||
"\tconst GLuint *indices; // faceCount * 3\n"
|
||||
"} OOPlanetDataLevel;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"extern const OOPlanetDataLevel kPlanetData[kOOPlanetDataLevels];\n", kFileName, kLevels);
|
||||
|
||||
fprintf(source,
|
||||
"/*\n"
|
||||
"\t%s.c\n"
|
||||
"\tFor Oolite\n"
|
||||
"\t\n"
|
||||
"\tThis file was automatically generated by tools/icosmesh. Do not modify.\n"
|
||||
"\t\n"
|
||||
"\tThis data may be used freely.\n"
|
||||
"*/\n"
|
||||
"\n"
|
||||
"#include \"OOPlanetData.h\"\n", kFileName);
|
||||
}
|
||||
|
||||
|
||||
static void WriteVertices(FILE *header, FILE *source, JAVertexSet *vertices)
|
||||
{
|
||||
unsigned i, count = vertices.count;
|
||||
|
||||
fprintf(header, "\n\nextern const GLfloat kOOPlanetVertices[%u];\n", count * 3);
|
||||
fprintf(header, "\nextern const GLfloat kOOPlanetTexCoords[%u];\n", count * 2);
|
||||
|
||||
fprintf(source, "\n\n/* Shared vertex array\n %u vertices\n*/\nconst GLfloat kOOPlanetVertices[%u] =\n{\n", count, count * 3);
|
||||
NSArray *data = [vertices positionArray];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (i != 0) fprintf(source, ",\n");
|
||||
fprintf(source, "\t%+.8ff, %+.8ff, %+.8ff", [[data objectAtIndex:i * 3] doubleValue], [[data objectAtIndex:i * 3 + 1] doubleValue], [[data objectAtIndex:i * 3 + 2] doubleValue]);
|
||||
}
|
||||
|
||||
fprintf(source, "\n};\n\n/* Shared texture coordinate array\n %u pairs\n*/\nconst GLfloat kOOPlanetTexCoords[%u] =\n{\n", count, count * 2);
|
||||
data = [vertices texCoordArray];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (i != 0) fprintf(source, ",\n");
|
||||
fprintf(source, "\t%+.8ff, %+.8ff", [[data objectAtIndex:i * 2] doubleValue], [[data objectAtIndex:i * 2 + 1] doubleValue]);
|
||||
}
|
||||
|
||||
fprintf(source, "\n};\n");
|
||||
}
|
||||
|
||||
|
||||
static void WriteMeshForTriangles(FILE *source, unsigned level, NSArray *triangles, JAVertexSet *vertices, unsigned *faceCount, unsigned *maxVertex)
|
||||
{
|
||||
JAIcosMesh *mesh = [JAIcosMesh meshWithVertexSet:vertices];
|
||||
[mesh addTriangles:triangles];
|
||||
WriteMesh(source, level, mesh);
|
||||
|
||||
*faceCount = mesh.faceCount;
|
||||
*maxVertex = mesh.maxIndex + 1;
|
||||
}
|
||||
|
||||
|
||||
static void WriteMesh(FILE *source, unsigned level, JAIcosMesh *mesh)
|
||||
{
|
||||
unsigned i, count = mesh.faceCount;
|
||||
NSArray *indices = [mesh indexArray];
|
||||
|
||||
fprintf(source, "\n\n/* Level %u index array\n %u faces\n*/\nstatic const GLuint kFaceIndicesLevel%u[%u] =\n{\n", level, count, level, count * 3);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (i != 0) fprintf(source, ",\n");
|
||||
fprintf(source, "\t%5u, %5u, %5u", [[indices objectAtIndex:i * 3] unsignedIntValue], [[indices objectAtIndex:i * 3 + 1] unsignedIntValue], [[indices objectAtIndex:i * 3 + 2] unsignedIntValue]);
|
||||
}
|
||||
fprintf(source, "\n};\n");
|
||||
}
|
||||
|
||||
|
||||
// Convert vector to latitude and longitude (or θ and φ).
|
||||
void VectorToCoordsRad(Vector v, double *latitude, double *longitude)
|
||||
{
|
||||
v = VectorNormal(v);
|
||||
|
||||
double las = v.y;
|
||||
if (las != 1.0f)
|
||||
{
|
||||
double lat = asin(las);
|
||||
double rlac = 1.0 / sqrt(1.0 - las * las); // Equivalent to abs(1/cos(lat))
|
||||
|
||||
if (latitude != NULL) *latitude = lat;
|
||||
if (longitude != NULL)
|
||||
{
|
||||
double los = v.x * rlac;
|
||||
double lon = asin(fmin(1.0, fmax(-1.0, los)));
|
||||
|
||||
// Quadrant rectification.
|
||||
if (v.z < 0.0f)
|
||||
{
|
||||
// We're beyond 90 degrees of longitude in some direction.
|
||||
if (v.x < 0.0f)
|
||||
{
|
||||
// ...specifically, west.
|
||||
lon = -M_PI - lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...specifically, east.
|
||||
lon = M_PI - lon;
|
||||
}
|
||||
}
|
||||
|
||||
*longitude = lon;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Straight up, avoid divide-by-zero
|
||||
if (latitude != NULL) *latitude = M_PI / 2.0f;
|
||||
if (longitude != NULL) *longitude = 0.0f; // arbitrary
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VectorToCoords0_1(Vector v, double *latitude, double *longitude)
|
||||
{
|
||||
VectorToCoordsRad(v, latitude, longitude);
|
||||
if (latitude != NULL) *latitude = 1.0 - (*latitude / M_PI + 0.5);
|
||||
if (longitude != NULL) *longitude = 1.0 - (*longitude / (M_PI * 2.0) + 0.5);
|
||||
}
|
BIN
tools/icosmesh/world.png
Normal file
BIN
tools/icosmesh/world.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 MiB |
Loading…
x
Reference in New Issue
Block a user