37#import "MyOpenGLView.h"
49#define NSIntegerMapKeyCallBacks NSIntMapKeyCallBacks
50#define NSIntegerMapValueCallBacks NSIntMapValueCallBacks
55static Vector base_vertex_array[MAX_PLANET_VERTICES];
56static int base_terrain_array[MAX_PLANET_VERTICES];
57static unsigned next_free_vertex;
58static NSMapTable *sEdgeToVertex;
60static int n_triangles[MAX_SUBDIVIDE];
61static int triangle_start[MAX_SUBDIVIDE];
62static GLuint vertex_index_array[3*(20+80+320+1280+5120+20480)];
64static GLfloat texture_uv_array[MAX_PLANET_VERTICES * 2];
67@interface PlanetEntity (OOPrivate) <OOGraphicsResetClient>
69- (double) sqrtZeroDistance;
71- (void) drawModelWithVertexArraysAndSubdivision: (
int) subdivide;
73- (void) initialiseBaseVertexArray;
76- (void) initialiseBaseTerrainArray:(
int) percent_land;
77- (void) paintVertex:(
unsigned) vi :(
int) seed;
78- (void) scaleVertices;
80- (id) initAsAtmosphereForPlanet:(PlanetEntity *)planet dictionary:(NSDictionary *)dict;
81- (void) setTextureColorForPlanet:(BOOL)isMain inSystem:(BOOL)isLocal;
83- (id) initMiniatureFromPlanet:(PlanetEntity*) planet withAlpha:(
float) alpha;
85- (void) loadTexture:(NSDictionary *)configuration;
86- (
OOTexture *) planetTextureWithInfo:(NSDictionary *)info;
87- (
OOTexture *) cloudTextureWithCloudColor:(
OOColor *)cloudColor cloudImpress:(GLfloat)cloud_impress cloudBias:(GLfloat)cloud_bias;
89- (void) deleteDisplayLists;
91- (void) setUseTexturedModel:(BOOL)flag;
95static unsigned baseVertexIndexForEdge(GLushort va, GLushort vb, BOOL textured);
106static const Vector kUntexturedVertices[] =
108 { +0.000000, -0.850664, -0.525710 },
109 { +0.000000, -0.850664, +0.525710 },
110 { +0.000000, +0.850664, +0.525710 },
111 { +0.000000, +0.850664, -0.525710 },
112 { -0.525710, +0.000000, -0.850664 },
113 { +0.525710, +0.000000, -0.850664 },
114 { +0.525710, +0.000000, +0.850664 },
115 { -0.525710, +0.000000, +0.850664 },
116 { -0.850664, -0.525710, +0.000000 },
117 { -0.850664, +0.525710, +0.000000 },
118 { +0.850664, +0.525710, +0.000000 },
119 { +0.850664, -0.525710, +0.000000 }
122static const BaseFace kUntexturedFaces[][3] =
124 { { 9, +0.600000, +0.666667 }, { 7, +0.800000, +0.666667 }, { 8, +0.800000, +0.333333 } },
125 { { 8, +0.800000, +0.333333 }, { 4, +0.600000, +0.333333 }, { 9, +0.600000, +0.666667 } },
126 { { 3, +0.400000, +0.666667 }, { 9, +0.600000, +0.666667 }, { 4, +0.600000, +0.333333 } },
127 { { 8, +0.800000, +0.333333 }, { 0, +0.500000, +0.000000 }, { 4, +0.600000, +0.333333 } },
128 { { 7, +0.800000, +0.666667 }, { 1, +1.000000, +0.333333 }, { 8, +0.800000, +0.333333 } },
129 { { 2, +0.500000, +1.000000 }, { 7, +0.800000, +0.666667 }, { 9, +0.600000, +0.666667 } },
130 { { 2, +0.500000, +1.000000 }, { 9, +0.600000, +0.666667 }, { 3, +0.400000, +0.666667 } },
131 { { 1, +1.000000, +0.333333 }, { 0, +0.500000, +0.000000 }, { 8, +0.800000, +0.333333 } },
132 { { 4, +0.600000, +0.333333 }, { 0, +0.500000, +0.000000 }, { 5, +0.400000, +0.333333 } },
133 { { 5, +0.400000, +0.333333 }, { 3, +0.400000, +0.666667 }, { 4, +0.600000, +0.333333 } },
134 { { 6, +1.000000, +0.666667 }, { 1, +1.000000, +0.333333 }, { 7, +0.800000, +0.666667 } },
135 { { 7, +0.800000, +0.666667 }, { 2, +0.500000, +1.000000 }, { 6, +1.000000, +0.666667 } },
136 { { 1, +0.000000, +0.333333 }, { 11, +0.200000, +0.333333 }, { 0, +0.500000, +0.000000 } },
137 { { 3, +0.400000, +0.666667 }, { 10, +0.200000, +0.666667 }, { 2, +0.500000, +1.000000 } },
138 { { 0, +0.500000, +0.000000 }, { 11, +0.200000, +0.333333 }, { 5, +0.400000, +0.333333 } },
139 { { 5, +0.400000, +0.333333 }, { 10, +0.200000, +0.666667 }, { 3, +0.400000, +0.666667 } },
140 { { 1, +0.000000, +0.333333 }, { 6, +0.000000, +0.666667 }, { 11, +0.200000, +0.333333 } },
141 { { 6, +0.000000, +0.666667 }, { 2, +0.500000, +1.000000 }, { 10, +0.200000, +0.666667 } },
142 { { 5, +0.400000, +0.333333 }, { 11, +0.200000, +0.333333 }, { 10, +0.200000, +0.666667 } },
143 { { 11, +0.200000, +0.333333 }, { 6, +0.000000, +0.666667 }, { 10, +0.200000, +0.666667 } }
147static const Vector kTexturedVertices[] =
149 { +0.525731, +0.000000, +0.850651 },
150 { -0.525731, +0.000000, +0.850651 },
151 { +0.525731, +0.000000, -0.850651 },
152 { -0.525731, +0.000000, -0.850651 },
153 { +0.000000, +0.850651, +0.525731 },
154 { +0.000000, +0.850651, -0.525731 },
155 { +0.000000, -0.850651, +0.525731 },
156 { +0.000000, -0.850651, -0.525731 },
157 { -0.850651, +0.525731, +0.000000 },
158 { +0.850651, +0.525731, +0.000000 },
159 { -0.850651, -0.525731, +0.000000 },
160 { +0.850651, -0.525731, +0.000000 },
161 { +0.000000, +0.850651, -0.525731 },
162 { +0.525731, +0.000000, -0.850651 }
165static const BaseFace kTexturedFaces[][3] =
167 { { 1, +0.400000, +0.666667 }, { 0, +0.600000, +0.666667 }, { 6, +0.500000, +0.333333 } },
168 { { 3, +0.100000, +0.333333 }, { 2, -0.100000, +0.333333 }, { 5, +0.000000, +0.666667 } },
169 { { 4, +0.500000, +1.000000 }, { 0, +0.600000, +0.666667 }, { 1, +0.400000, +0.666667 } },
170 { { 4, +0.500000, +1.000000 }, { 1, +0.400000, +0.666667 }, { 8, +0.200000, +0.666667 } },
171 { { 12, +1.000000, +0.666667 }, { 13, +0.900000, +0.333333 }, { 9, +0.800000, +0.666667 } },
172 { { 5, +0.000000, +0.666667 }, { 4, +0.500000, +1.000000 }, { 8, +0.200000, +0.666667 } },
173 { { 6, +0.500000, +0.333333 }, { 0, +0.600000, +0.666667 }, { 11, +0.700000, +0.333333 } },
174 { { 7, +0.500000, +0.000000 }, { 2, -0.100000, +0.333333 }, { 3, +0.100000, +0.333333 } },
175 { { 7, +0.500000, +0.000000 }, { 3, +0.100000, +0.333333 }, { 10, +0.300000, +0.333333 } },
176 { { 7, +0.500000, +0.000000 }, { 6, +0.500000, +0.333333 }, { 11, +0.700000, +0.333333 } },
177 { { 8, +0.200000, +0.666667 }, { 1, +0.400000, +0.666667 }, { 10, +0.300000, +0.333333 } },
178 { { 8, +0.200000, +0.666667 }, { 3, +0.100000, +0.333333 }, { 5, +0.000000, +0.666667 } },
179 { { 9, +0.800000, +0.666667 }, { 0, +0.600000, +0.666667 }, { 4, +0.500000, +1.000000 } },
180 { { 9, +0.800000, +0.666667 }, { 13, +0.900000, +0.333333 }, { 11, +0.700000, +0.333333 } },
181 { { 9, +0.800000, +0.666667 }, { 4, +0.500000, +1.000000 }, { 12, +1.000000, +0.666667 } },
182 { { 10, +0.300000, +0.333333 }, { 1, +0.400000, +0.666667 }, { 6, +0.500000, +0.333333 } },
183 { { 10, +0.300000, +0.333333 }, { 3, +0.100000, +0.333333 }, { 8, +0.200000, +0.666667 } },
184 { { 10, +0.300000, +0.333333 }, { 6, +0.500000, +0.333333 }, { 7, +0.500000, +0.000000 } },
185 { { 11, +0.700000, +0.333333 }, { 0, +0.600000, +0.666667 }, { 9, +0.800000, +0.666667 } },
186 { { 11, +0.700000, +0.333333 }, { 13, +0.900000, +0.333333 }, { 7, +0.500000, +0.000000 } }
190@implementation PlanetEntity
195 [NSException raise:NSInternalInconsistencyException format:@"%s, believed dead, called.", __PRETTY_FUNCTION__];
200- (id) initAsAtmosphereForPlanet:(PlanetEntity *)planet dictionary:(NSDictionary *)dict
202 BOOL procGen = [UNIVERSE doProcedurallyTexturedPlanets];
204 if (dict ==
nil) dict = [NSDictionary dictionary];
210 polar_color_factor = 1.0;
212#define CLEAR_SKY_ALPHA 0.05
213#define CLOUD_ALPHA 0.50
214#define POLAR_CLEAR_SKY_ALPHA 0.34
215#define POLAR_CLOUD_ALPHA 0.75
220 amb_land[3] = CLEAR_SKY_ALPHA;
224 amb_sea[3] = CLOUD_ALPHA;
228 amb_polar_land[3] = POLAR_CLEAR_SKY_ALPHA;
232 amb_polar_sea[3] = POLAR_CLOUD_ALPHA;
246 cloudAlpha = OOClamp_0_1_f([dict oo_floatForKey:
@"cloud_alpha" defaultValue:1.0]);
248 if (clearSkyColor !=
nil)
253 if (cloudColor !=
nil)
258 if (polarClearSkyColor !=
nil)
260 [polarClearSkyColor
getRed:&amb_polar_land[0]
green:&amb_polar_land[1]
blue:&amb_polar_land[2]
alpha:&amb_polar_land[3]];
262 else if (clearSkyColor !=
nil)
264 memmove(amb_polar_land, amb_land,
sizeof amb_polar_land);
265 amb_polar_land[3] = OOClamp_0_1_f(amb_polar_land[3] * (POLAR_CLEAR_SKY_ALPHA / CLEAR_SKY_ALPHA));
268 if (polarCloudColor !=
nil)
270 [polarCloudColor
getRed:&amb_polar_sea[0]
green:&amb_polar_sea[1]
blue:&amb_polar_sea[2]
alpha:&amb_polar_sea[3]];
272 else if (cloudColor !=
nil)
274 memmove(amb_polar_sea, amb_sea,
sizeof amb_polar_sea);
275 amb_polar_sea[3] *= (POLAR_CLOUD_ALPHA / CLOUD_ALPHA);
279 amb_sea[3] *= cloudAlpha;
280 amb_polar_land[3] *= cloudAlpha;
281 amb_polar_sea[3] *= cloudAlpha;
283 amb_sea[3] = OOClamp_0_1_f(amb_sea[3]);
284 amb_polar_sea[3] = OOClamp_0_1_f(amb_polar_sea[3]);
293 float cloud_bias = -0.01 * (float)percent_land;
294 float cloud_impress = 1.0 - cloud_bias;
296 _texture = [
self cloudTextureWithCloudColor:cloudColor cloudImpress:cloud_impress cloudBias:cloud_bias];
306 OOLogERR(
@"planet.atmosphere.init.noPlanet",
@"planet entity initAsAtmosphereForPlanet: no planet found.");
310 [
self setOwner: planet];
312 position = [planet position];
313 orientation = [planet orientation];
320 shuttles_on_ground = 0;
321 last_launch_time = 0.0;
322 shuttle_launch_interval = 3600.0;
324 scanClass = CLASS_NO_DRAW;
335 [
self setUseTexturedModel:YES];
336 [
self initialiseBaseVertexArray];
337 [
self initialiseBaseTerrainArray:percent_land];
339 for (i = 0; i < next_free_vertex; i++)
341 [
self paintVertex:i :planet_seed];
344 [
self scaleVertices];
347 rotational_velocity = [dict oo_floatForKey:@"atmosphere_rotational_velocity" defaultValue:[planet rotationalVelocity]*(0.9+(randf()*0.2))];
349 root_planet = planet;
362 shuttles_on_ground = 0;
363 last_launch_time = 0.0;
364 shuttle_launch_interval = 3600.0;
365 [
self setStatus:STATUS_COCKPIT_DISPLAY];
367 [
self scaleVertices];
368 if (atmosphere !=
nil)
371 [atmosphere scaleVertices];
373 rotational_velocity = 0.04;
378- (id) initFromDictionary:(NSDictionary*)dict withAtmosphere:(BOOL)atmo andSeed:(
Random_Seed)p_seed
380 BOOL procGen = [UNIVERSE doProcedurallyTexturedPlanets];
382 if (dict ==
nil) dict = [NSDictionary dictionary];
390 planet_seed = p_seed.
a * 13 + p_seed.c * 11 + p_seed.e * 7;
392 planet_seed = p_seed.
a * 7 + p_seed.c * 11 + p_seed.e * 13;
394 OOTexture *texture = [dict oo_objectOfClass:[
OOTexture class] forKey:@"_oo_textureObject"];
397 _texture = [texture
retain];
398 isTextureImage = [dict oo_boolForKey:@"_oo_isExplicitlyTextured"];
402 NSDictionary *textureSpec = [dict oo_textureSpecifierForKey:@"texture" defaultName:nil];
403 if (textureSpec !=
nil)
405 [
self loadTexture:textureSpec];
415 NSString *seedStr = [dict oo_stringForKey:@"seed"];
425 OOLogERR(
@"planet.fromDict",
@"could not interpret \"%@\
" as planet seed, using default.", seedStr);
432 NSMutableDictionary *planetInfo = [NSMutableDictionary dictionaryWithDictionary:[UNIVERSE generateSystemData:p_seed]];
433 int radius_km = [dict oo_intForKey:KEY_RADIUS
434 defaultValue:[planetInfo oo_intForKey:KEY_RADIUS]];
435 int techlevel = [dict oo_intForKey:KEY_TECHLEVEL
436 defaultValue:[planetInfo oo_intForKey:KEY_TECHLEVEL]];
438 shuttles_on_ground = 1 + floor(techlevel * 0.5);
439 last_launch_time = 0.0;
440 shuttle_launch_interval = 3600.0 / shuttles_on_ground;
442 last_launch_time = [UNIVERSE getTime] + 30.0 - shuttle_launch_interval;
444 collision_radius = radius_km * 10.0;
446 scanClass = CLASS_NO_DRAW;
453 [
self setUseTexturedModel:(procGen || _texture != nil)];
455 int percent_land = [planetInfo oo_intForKey:@"percent_land" defaultValue:24 + (gen_rnd_number() % 48)];
465 [planetInfo setObject:[NSNumber numberWithFloat:0.01 * percent_land] forKey:@"land_fraction"];
467 polar_color_factor = [dict oo_doubleForKey:@"polar_color_factor" defaultValue:0.5f];
469 Vector land_hsb, sea_hsb, land_polar_hsb, sea_polar_hsb;
474 land_hsb.x = 0.0; land_hsb.y = 0.0; land_hsb.z = 1.0;
475 sea_hsb.x = 0.0; sea_hsb.y = 1.0; sea_hsb.z = 1.0;
477 [
self setTextureColorForPlanet:!![dict objectForKey:@"mainForLocalSystem"] inSystem:[dict oo_boolForKey:@"mainForLocalSystem" defaultValue:NO]];
484 while (dot_product(land_hsb,sea_hsb) > .80)
494 land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 4.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0);
495 sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 4.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0);
506 amb_sea[0] = [amb_sea_color redComponent];
507 amb_sea[1] = [amb_sea_color blueComponent];
508 amb_sea[2] = [amb_sea_color greenComponent];
510 amb_polar_land[0] = [amb_polar_land_color redComponent];
511 amb_polar_land[1] = [amb_polar_land_color blueComponent];
512 amb_polar_land[2] = [amb_polar_land_color greenComponent];
513 amb_polar_land[3] = 1.0;
514 amb_polar_sea[0] = [amb_polar_sea_color redComponent];
515 amb_polar_sea[1] = [amb_polar_sea_color blueComponent];
516 amb_polar_sea[2] = [amb_polar_sea_color greenComponent];
517 amb_polar_sea[3] = 1.0;
519 [planetInfo setObject:amb_land_color forKey:@"land_color"];
520 [planetInfo setObject:amb_sea_color forKey:@"sea_color"];
521 [planetInfo setObject:amb_polar_land_color forKey:@"polar_land_color"];
522 [planetInfo setObject:amb_polar_sea_color forKey:@"polar_sea_color"];
525 if (procGen && _texture ==
nil)
527 _texture = [
self planetTextureWithInfo:planetInfo];
532 [
self initialiseBaseVertexArray];
533 [
self initialiseBaseTerrainArray:percent_land];
535 for (i = 0; i < next_free_vertex; i++)
537 [
self paintVertex:i :planet_seed];
540 [
self scaleVertices];
542 if ([dict objectForKey:
@"rotational_velocity"])
544 rotational_velocity = [dict oo_floatForKey:@"rotational_velocity" defaultValue:0.01f * randf()];
548 rotational_velocity = [planetInfo oo_floatForKey:@"rotation_speed" defaultValue:0.002 * (0.5+0.5*randf())];
549 rotational_velocity *= [planetInfo oo_floatForKey:@"rotation_speed_factor" defaultValue:1.0f];
553 NSDictionary *atmoDict = dict;
554 if (_texture !=
nil) atmoDict = [NSDictionary dictionaryWithObjectsAndKeys:@"0", @"percent_cloud", [NSNumber numberWithFloat:[planetInfo oo_floatForKey:@"cloud_alpha" defaultValue:1.0]], @"cloud_alpha", nil];
555 if (atmo) atmosphere = [[PlanetEntity alloc] initAsAtmosphereForPlanet:self dictionary:atmoDict];
561 energy = collision_radius * 1000.0;
569 int deltaT = floor(fmod([
PLAYER clockTimeAdjusted], 86400));
572 [
self setStatus:STATUS_ACTIVE];
582 [
self deleteDisplayLists];
594- (NSString*) descriptionComponents
596 NSString *typeString;
600 typeString =
@"STELLAR_TYPE_MINIATURE";
break;
602 typeString =
@"STELLAR_TYPE_NORMAL_PLANET";
break;
604 typeString =
@"STELLAR_TYPE_ATMOSPHERE";
break;
606 typeString =
@"STELLAR_TYPE_MOON";
break;
609 typeString =
@"UNKNOWN";
611 return [NSString stringWithFormat:@"ID: %u position: %@ type: %@ radius: %.3fkm", [
self universalID], HPVectorDescription([
self position]), typeString, 0.001 * [
self radius]];
633- (BOOL) checkCloseCollisionWith:(
Entity *)other
637 OOLog(
@"planet.collide",
@"PLANET Collision!");
645 if ([ship behaviour] == BEHAVIOUR_LAND_ON_PLANET)
650 if ([ship reportAIMessages])
653 OOLog(
@"planet.collide.shipHit",
@"DEBUG: %@ %d collided with planet at (%.1f,%.1f,%.1f)",[ship name], [ship universalID], p1.x,p1.y,p1.z);
664 [
super update:delta_t];
665 sqrt_zero_distance = sqrt(cam_zero_distance);
672 double alt = sqrt_zero_distance - collision_radius;
673 double atmo = 10.0 * (atmosphere->collision_radius - collision_radius);
675 if ((alt > 0)&&(alt <= atmo))
677 double aleph = (atmo - alt) / atmo;
678 if (aleph < 0.0) aleph = 0.0;
679 if (aleph > 1.0) aleph = 1.0;
681 [UNIVERSE setSkyColorRed:0.8 * aleph * aleph
682 green:0.8 * aleph * aleph
686 else if (alt > 0 && alt <= atmo * 1.5)
693 [UNIVERSE setSkyColorRed:0.0f
701 double ugt = [UNIVERSE getTime];
703 if ((shuttles_on_ground > 0)&&(ugt > last_launch_time + shuttle_launch_interval))
705 [
self launchShuttle];
706 shuttles_on_ground--;
707 last_launch_time = ugt;
713 if (atmosphere) [atmosphere update:delta_t];
715 [
self orientationChanged];
722 [
self orientationChanged];
732- (void) setPosition:(HPVector)posn
735 [atmosphere setPosition:posn];
739- (void) setOrientation:(Quaternion)inOrientation
742 [
super setOrientation:inOrientation];
743 if (atmosphere) [atmosphere setOrientation:inOrientation];
747- (void) setUseTexturedModel:(BOOL)flag
751 useTexturedModel = YES;
752 vertexCount =
sizeof kTexturedVertices /
sizeof *kTexturedVertices;
756 useTexturedModel = NO;
757 vertexCount =
sizeof kUntexturedVertices /
sizeof *kTexturedVertices;
763- (void) drawImmediate:(
bool)immediate translucent:(
bool)translucent
765 if ([
UNIVERSE breakPatternHide] || translucent || immediate)
return;
767 if (radWithAtmosphere * radWithAtmosphere * 1.1 < cam_zero_distance)
772 if (![
UNIVERSE viewFrustumIntersectsSphereAt:cameraRelativePosition withRadius:radWithAtmosphere])
779 [
self drawUnconditionally];
783- (void) drawUnconditionally
785 uint8_t subdivideLevel = 2;
787 double drawFactor = [[UNIVERSE gameView] viewSize].width / 100.0;
788 double drawRatio2 = drawFactor * collision_radius / sqrt_zero_distance;
790 if (cam_zero_distance > 0.0)
792 subdivideLevel = 2 + floor(drawRatio2);
793 if (subdivideLevel > 4) subdivideLevel = 4;
798 subdivideLevel = [UNIVERSE reducedDetail]? 3 : 4;
801 lastSubdivideLevel = subdivideLevel;
804 OOGL(glPushAttrib(GL_ENABLE_BIT));
808 GLfloat specular[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
809 OOGL(glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular));
810 OOGL(glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0));
824 if (cam_zero_distance > collision_radius * collision_radius * 25)
826 ignoreDepthBuffer |= YES;
829 [_texture ensureFinishedLoading];
836 subdivideLevel = root_planet->lastSubdivideLevel;
838 OOGLMultModelVew(rotMatrix);
839 OOGL(glEnable(GL_BLEND));
856 GLfloat mat1[] = { 1.0, 1.0, 1.0, 1.0 };
860 if ([_texture isCubeMap])
862#if OO_TEXTURE_CUBE_MAP
863 OOGL(glDisable(GL_TEXTURE_2D));
864 OOGL(glEnable(GL_TEXTURE_CUBE_MAP));
871 OOGL(glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, mat1));
876 OOGL(glDisable(GL_TEXTURE_2D));
880 OOGL(glShadeModel(GL_SMOOTH));
883 if (ignoreDepthBuffer)
885 OOGL(glDisable(GL_DEPTH_TEST));
888 OOGL(glColor4fv(mat1));
889 OOGL(glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat1));
891 OOGL(glEnableClientState(GL_COLOR_ARRAY));
892 OOGL(glColorPointer(4, GL_FLOAT, 0, vertexdata.color_array));
894 OOGL(glVertexPointer(3, GL_FLOAT, 0, vertexdata.vertex_array));
896 OOGL(glNormalPointer(GL_FLOAT, 0, vertexdata.normal_array));
900 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
901 if ([_texture isCubeMap])
903 OOGL(glTexCoordPointer(3, GL_FLOAT, 0, vertexdata.vertex_array));
907 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, vertexdata.uv_array));
912 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
915 if (displayListNames[subdivideLevel] != 0)
917 OOGL(glCallList(displayListNames[subdivideLevel]));
922 OOGL(displayListNames[subdivideLevel] = glGenLists(1));
923 if (displayListNames[subdivideLevel] != 0)
925 OOGL(glNewList(displayListNames[subdivideLevel], GL_COMPILE_AND_EXECUTE));
927 OOGL(glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE));
928 OOGL(glEnable(GL_COLOR_MATERIAL));
930 [
self drawModelWithVertexArraysAndSubdivision:subdivideLevel];
932 OOGL(glDisable(GL_COLOR_MATERIAL));
937#if OO_TEXTURE_CUBE_MAP
938 if ([_texture isCubeMap])
940 OOGL(glDisable(GL_TEXTURE_CUBE_MAP));
941 OOGL(glEnable(GL_TEXTURE_2D));
945 OOGL(glDisableClientState(GL_COLOR_ARRAY));
946 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
947 OOGL(glEnable(GL_DEPTH_TEST));
965 if (ignoreDepthBuffer)
967 OOGL(glEnable(GL_DEPTH_TEST));
969 OOGL(glEnable(GL_TEXTURE_2D));
971 OOGL(glDisable(GL_BLEND));
986 [atmosphere drawImmediate:false translucent:false];
994- (PlanetEntity *) atmosphere
1009 return _texture !=
nil;
1013- (NSString *) textureFileName
1015 return _textureFileName;
1019- (void) setTextureColorForPlanet:(BOOL)isMain inSystem:(BOOL)isLocal
1021 Vector land_hsb, land_polar_hsb;
1022 land_hsb.x = 0.0; land_hsb.y = 0.0; land_hsb.z = 1.0;
1031 land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0);
1036 amb_sea[3] = amb_land[3] = 1.0;
1040 amb_polar_sea[3] =amb_polar_land[3] = 1.0;
1044- (BOOL) setUpPlanetFromTexture:(NSString *)fileName
1046 if (fileName ==
nil)
return NO;
1048 [
self loadTexture:OOTextureSpecFromObject(fileName, nil)];
1049 [
self deleteDisplayLists];
1052 [
self setUseTexturedModel:YES];
1056 [
self setTextureColorForPlanet:([UNIVERSE planet] == self) inSystem:YES];
1058 [
self initialiseBaseVertexArray];
1059 [
self initialiseBaseTerrainArray:100];
1060 for (i = 0; i < next_free_vertex; i++)
1062 [
self paintVertex:i :planet_seed];
1065 [
self scaleVertices];
1067 GLfloat oldCloudAlpha = 0.0;
1070 oldCloudAlpha = [atmosphere amb_sea][3] / CLOUD_ALPHA;
1073 NSDictionary *atmo_dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"0", @"percent_cloud", [NSNumber numberWithFloat:oldCloudAlpha], @"cloud_alpha", nil];
1074 [atmosphere autorelease];
1075 atmosphere = [
self hasAtmosphere] ? [[PlanetEntity alloc] initAsAtmosphereForPlanet:self dictionary:atmo_dictionary] :
nil;
1079 return [
self isTextured];
1083- (double) polar_color_factor
1085 return polar_color_factor;
1089- (GLfloat *) amb_land
1095- (GLfloat *) amb_polar_land
1097 return amb_polar_land;
1101- (GLfloat *) amb_sea
1107- (GLfloat *) amb_polar_sea
1109 return amb_polar_sea;
1127 return collision_radius;
1131- (void) setRadius:(GLfloat) rad
1133 collision_radius = rad;
1136- (double) rotationalVelocity
1138 return rotational_velocity;
1141- (void) setRotationalVelocity:(
double) v
1145 [atmosphere setRotationalVelocity:[atmosphere rotationalVelocity] * v / [
self rotationalVelocity]];
1147 rotational_velocity = v;
1151- (double) sqrtZeroDistance
1153 return sqrt_zero_distance;
1157- (BOOL) hasAtmosphere
1159 return atmosphere !=
nil;
1163- (void) drawModelWithVertexArraysAndSubdivision: (
int) subdivide
1165 OOGL(glDrawElements(GL_TRIANGLES, 3 * n_triangles[subdivide], GL_UNSIGNED_INT, &vertexdata.index_array[triangle_start[subdivide]]));
1169- (void) launchShuttle
1173 HPVector launch_pos = position;
1174 double start_distance = collision_radius + 125.0;
1180 launch_pos.x += start_distance * vf.
x;
1181 launch_pos.y += start_distance * vf.
y;
1182 launch_pos.z += start_distance * vf.z;
1184 shuttle_ship = [UNIVERSE newShipWithRole:@"shuttle"];
1187 if (![shuttle_ship crew])
1197 [shuttle_ship
switchAITo:@"oolite-shuttleAI.js"];
1198 [UNIVERSE addEntity:shuttle_ship];
1200 [shuttle_ship release];
1205- (void) welcomeShuttle:(
ShipEntity *) shuttle
1207 shuttles_on_ground++;
1211- (void) initialiseBaseVertexArray
1213 BOOL isTextured = [
self isTextured];
1214 static BOOL lastOneWasTextured;
1216 if (lastOneWasTextured != isTextured)
1218 if (sEdgeToVertex != NULL)
1220 NSFreeMapTable(sEdgeToVertex);
1221 sEdgeToVertex = NULL;
1223 lastOneWasTextured = isTextured;
1226 if (sEdgeToVertex == NULL)
1228 sEdgeToVertex = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSIntegerMapValueCallBacks, 7680);
1229 next_free_vertex = 0;
1231 const Vector *vertices = NULL;
1232 const BaseFace (*faces)[3] = NULL;
1233 GLuint faceCount = 0;
1234 if (useTexturedModel)
1236 vertices = kTexturedVertices;
1237 faces = kTexturedFaces;
1238 faceCount =
sizeof kTexturedFaces /
sizeof *kTexturedFaces;
1242 vertices = kUntexturedVertices;
1243 faces = kUntexturedFaces;
1244 faceCount =
sizeof kUntexturedFaces /
sizeof *kUntexturedFaces;
1249 for (vi = 0; vi < vertexCount; vi++)
1251 base_vertex_array[next_free_vertex++] = vertices[vi];
1255 triangle_start[0] = 0;
1256 n_triangles[0] = faceCount;
1258 for (fi = 0; fi < faceCount; fi++)
1261 for (j = 0; j < 3; j++)
1263 vertex_index_array[fi * 3 + j] = faces[fi][j].v;
1264 texture_uv_array[faces[fi][j].v * 2 + 0] = faces[fi][j].s;
1265 texture_uv_array[faces[fi][j].v * 2 + 1] = faces[fi][j].t;
1271 for (sublevel = 0; sublevel <
MAX_SUBDIVIDE - 1; sublevel++)
1273 int newlevel = sublevel + 1;
1274 triangle_start[newlevel] = triangle_start[sublevel] + n_triangles[sublevel] * 3;
1275 n_triangles[newlevel] = n_triangles[sublevel] * 4;
1278 for (tri = 0; tri < n_triangles[sublevel]; tri++)
1281 int v0 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 0];
1282 int v1 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 1];
1283 int v2 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 2];
1284 int v01 = baseVertexIndexForEdge(v0, v1, isTextured);
1285 int v12 = baseVertexIndexForEdge(v1, v2, isTextured);
1286 int v20 = baseVertexIndexForEdge(v2, v0, isTextured);
1288 vertex_index_array[triangle_start[newlevel] + tri * 12 + 0] = v0;
1289 vertex_index_array[triangle_start[newlevel] + tri * 12 + 1] = v01;
1290 vertex_index_array[triangle_start[newlevel] + tri * 12 + 2] = v20;
1292 vertex_index_array[triangle_start[newlevel] + tri * 12 + 3] = v01;
1293 vertex_index_array[triangle_start[newlevel] + tri * 12 + 4] = v1;
1294 vertex_index_array[triangle_start[newlevel] + tri * 12 + 5] = v12;
1296 vertex_index_array[triangle_start[newlevel] + tri * 12 + 6] = v20;
1297 vertex_index_array[triangle_start[newlevel] + tri * 12 + 7] = v12;
1298 vertex_index_array[triangle_start[newlevel] + tri * 12 + 8] = v2;
1300 vertex_index_array[triangle_start[newlevel] + tri * 12 + 9] = v01;
1301 vertex_index_array[triangle_start[newlevel] + tri * 12 +10] = v12;
1302 vertex_index_array[triangle_start[newlevel] + tri * 12 +11] = v20;
1310 for (i = 0; i < MAX_TRI_INDICES; i++)
1312 vertexdata.index_array[i] = vertex_index_array[i];
1317static unsigned baseVertexIndexForEdge(GLushort va, GLushort vb, BOOL textured)
1325 void *key = (
void *)(((uintptr_t)va << 16) | vb);
1326 uintptr_t num = (uintptr_t)NSMapGet(sEdgeToVertex, key);
1330 return (
unsigned)num - 1;
1334 unsigned vindex = next_free_vertex++;
1335 NSCAssert(vindex <
sizeof base_vertex_array /
sizeof *base_vertex_array,
@"Vertex array overflow in planet setup.");
1338 Vector pos = vector_add(base_vertex_array[va], base_vertex_array[vb]);
1339 pos = vector_normal(pos);
1340 base_vertex_array[vindex] = pos;
1345 NSPoint uva = (NSPoint){ texture_uv_array[va * 2], texture_uv_array[va * 2 + 1] };
1346 NSPoint uvb = (NSPoint){ texture_uv_array[vb * 2], texture_uv_array[vb * 2 + 1] };
1349 if (uva.y == 0.0 || uva.y == 1.0) uva.x = uvb.x;
1350 if (uvb.y == 0.0 || uvb.y == 1.0) uvb.x = uva.x;
1352 texture_uv_array[vindex * 2] = 0.5 * (uva.x + uvb.
x);
1353 texture_uv_array[vindex * 2 + 1] = 0.5 * (uva.y + uvb.
y);
1358 NSMapInsertKnownAbsent(sEdgeToVertex, key, (
void *)num);
1364- (void) initialiseBaseTerrainArray:(
int) percent_land
1369 if (percent_land >= 0)
1372 for (vi = 0; vi < vertexCount; vi++)
1375 base_terrain_array[vi] = 0;
1377 base_terrain_array[vi] = 100;
1383 BOOL isTextured = [
self isTextured];
1386 for (sublevel = 0; sublevel <
MAX_SUBDIVIDE - 1; sublevel++)
1389 for (tri = 0; tri < n_triangles[sublevel]; tri++)
1392 int v0 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 0];
1393 int v1 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 1];
1394 int v2 = vertex_index_array[triangle_start[sublevel] + tri * 3 + 2];
1395 int v01 = baseVertexIndexForEdge(v0, v1, isTextured);
1396 int v12 = baseVertexIndexForEdge(v1, v2, isTextured);
1397 int v20 = baseVertexIndexForEdge(v2, v0, isTextured);
1399 if (base_terrain_array[v0] == base_terrain_array[v1])
1400 base_terrain_array[v01] = base_terrain_array[v0];
1403 uint32_t s1 = 0xffff0000 * base_vertex_array[v01].x;
1404 uint32_t s2 = 0x00ffff00 * base_vertex_array[v01].y;
1405 uint32_t s3 = 0x0000ffff * base_vertex_array[v01].z;
1407 base_terrain_array[v01] = (
ranrot_rand() & 4) *25;
1410 if (base_terrain_array[v1] == base_terrain_array[v2])
1411 base_terrain_array[v12] = base_terrain_array[v1];
1414 uint32_t s1 = 0xffff0000 * base_vertex_array[v12].x;
1415 uint32_t s2 = 0x00ffff00 * base_vertex_array[v12].y;
1416 uint32_t s3 = 0x0000ffff * base_vertex_array[v12].z;
1418 base_terrain_array[v12] = (
ranrot_rand() & 4) *25;
1421 if (base_terrain_array[v2] == base_terrain_array[v0])
1422 base_terrain_array[v20] = base_terrain_array[v2];
1425 uint32_t s1 = 0xffff0000 * base_vertex_array[v20].x;
1426 uint32_t s2 = 0x00ffff00 * base_vertex_array[v20].y;
1427 uint32_t s3 = 0x0000ffff * base_vertex_array[v20].z;
1429 base_terrain_array[v20] = (
ranrot_rand() & 4) *25;
1438- (void) paintVertex:(
unsigned) vi :(
int) seed
1441 BOOL isTextured = _texture !=
nil;
1443 GLfloat paint_land[4] = { 0.2, 0.9, 0.0, 1.0};
1444 GLfloat paint_sea[4] = { 0.0, 0.2, 0.9, 1.0};
1445 GLfloat paint_color[4];
1446 Vector v = base_vertex_array[vi];
1447 int r = isTextured ? 0 : base_terrain_array[vi];
1449 double pole_blend = v.z * v.z * polar_color_factor;
1450 if (pole_blend < 0.0) pole_blend = 0.0;
1451 if (pole_blend > 1.0) pole_blend = 1.0;
1453 paint_land[0] = (1.0 - pole_blend)*amb_land[0] + pole_blend*amb_polar_land[0];
1454 paint_land[1] = (1.0 - pole_blend)*amb_land[1] + pole_blend*amb_polar_land[1];
1455 paint_land[2] = (1.0 - pole_blend)*amb_land[2] + pole_blend*amb_polar_land[2];
1456 paint_sea[0] = (1.0 - pole_blend)*amb_sea[0] + pole_blend*amb_polar_sea[0];
1457 paint_sea[1] = (1.0 - pole_blend)*amb_sea[1] + pole_blend*amb_polar_sea[1];
1458 paint_sea[2] = (1.0 - pole_blend)*amb_sea[2] + pole_blend*amb_polar_sea[2];
1461 paint_land[3] = (1.0 - pole_blend)*amb_land[3] + pole_blend*amb_polar_land[3];
1462 paint_sea[3] = (1.0 - pole_blend)*amb_sea[3] + pole_blend*amb_polar_sea[3];
1465 ranrot_srand((uint32_t)(seed+v.x*1000+v.y*100+v.z*10));
1467 for (i = 0; i < 3; i++)
1470 paint_land[i] += (cv - 0.5)*0.1;
1471 paint_sea[i] += (cv - 0.5)*0.1;
1474 for (i = 0; i < 4; i++)
1477 paint_color[i] = 1.0;
1479 paint_color[i] = (r * paint_sea[i])*0.01 + ((100 - r) * paint_land[i])*0.01;
1481 vertexdata.color_array[vi*4 + i] = paint_color[i];
1488- (void) scaleVertices
1491 for (vi = 0; vi < next_free_vertex; vi++)
1493 Vector v = base_vertex_array[vi];
1494 vertexdata.normal_array[vi] = v;
1495 vertexdata.vertex_array[vi] = make_vector(v.x * collision_radius, v.y * collision_radius, v.z * collision_radius);
1497 vertexdata.uv_array[vi * 2] = texture_uv_array[vi * 2];
1498 vertexdata.uv_array[vi * 2 + 1] = texture_uv_array[vi * 2 + 1];
1503- (void) deleteDisplayLists
1508 if (displayListNames[i] != 0)
1510 glDeleteLists(displayListNames[i], 1);
1511 displayListNames[i] = 0;
1517- (void)resetGraphicsState
1519 [
self deleteDisplayLists];
1523- (BOOL) isExplicitlyTextured
1525 return isTextureImage;
1535- (void) loadTexture:(NSDictionary *)configuration
1541 [_textureFileName release];
1542 if (_texture !=
nil)
1544 _textureFileName = [[configuration oo_stringForKey:@"name"] copy];
1545 isTextureImage = YES;
1549 _textureFileName =
nil;
1550 isTextureImage = NO;
1561- (
OOTexture *) planetTextureWithInfo:(NSDictionary *)info
1563 unsigned char *data;
1564 GLuint width, height;
1577 textureOptions:kOOTextureDefaultOptions | kOOTextureRepeatS
1579 [loader autorelease];
1585- (
OOTexture *) cloudTextureWithCloudColor:(
OOColor *)cloudColor cloudImpress:(GLfloat)cloud_impress cloudBias:(GLfloat)cloud_bias
1587 unsigned char *data;
1588 GLuint width, height;
1603 textureOptions:kOOTextureDefaultOptions | kOOTextureRepeatS
1605 [loader autorelease];
1612- (NSSet *) allTextures
1614 if (_texture !=
nil)
return [NSSet setWithObject:_texture];
#define OOLogERR(class, format,...)
#define OOLog(class, format,...)
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
OOMatrix OOGLPopModelView(void)
void OOGLWireframeModeOn(void)
void OOGLWireframeModeOff(void)
#define OOVerifyOpenGLState()
BOOL OOCheckOpenGLErrors(NSString *format,...)
#define OOSetOpenGLState(STATE)
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize)
Vector vector_up_from_quaternion(Quaternion quat)
Vector vector_forward_from_quaternion(Quaternion quat)
void quaternion_set_random(Quaternion *quat)
void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, OOScalar angle)
#define PLANET_MINIATURE_FACTOR
@ STELLAR_TYPE_ATMOSPHERE
@ STELLAR_TYPE_NORMAL_PLANET
Random_Seed RandomSeedFromString(NSString *abcdefString)
BOOL ScanVectorFromString(NSString *xyzString, Vector *outVector)
const Vector kBasisYVector
void fillRanNoiseBuffer()
void setOrientation:(Quaternion quat)
void setScanClass:(OOScanClass sClass)
void setPosition:(HPVector posn)
OOColor * colorWithRed:green:blue:alpha:(float red,[green] float green,[blue] float blue,[alpha] float alpha)
OOColor * colorWithDescription:(id description)
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
OOColor * colorWithHue:saturation:brightness:alpha:(float hue,[saturation] float saturation,[brightness] float brightness,[alpha] float alpha)
void registerClient:(id< OOGraphicsResetClient > client)
void unregisterClient:(id< OOGraphicsResetClient > client)
OOGraphicsResetManager * sharedManager()
id textureWithGenerator:(OOTextureGenerator *generator)
id textureWithConfiguration:extraOptions:(id configuration,[extraOptions] OOTextureFlags extraOptions)
void setCargoFlag:(OOCargoFlag flag)
void setSingleCrewWithRole:(NSString *crewRole)
void switchAITo:(NSString *aiString)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
RANROTSeed RANROTGetFullSeed(void)
void ranrot_srand(uint32_t seed)
void setRandomSeed(RNG_Seed a_seed)
RNG_Seed currentRandomSeed(void)
void RANROTSetFullSeed(RANROTSeed seed)
void seed_for_planet_description(Random_Seed s_seed)
OOINLINE int is_nil_seed(Random_Seed a_seed) INLINE_CONST_FUNC