32#define DEBUG_DUMP ( 0 && OOLITE_DEBUG)
33#define DEBUG_DUMP_RAW ( 1 && DEBUG_DUMP)
36#define ALBEDO_FACTOR 0.7f
43#ifndef TEXGEN_TEST_RIG
49#import "MyOpenGLView.h"
53#define FREE(x) do { if (0) { void *x__ = x; x__ = x__; } void **x_ = (void **)&(x); free(*x_); *x_ = NULL; } while (0)
56#define PLANET_TEXTURE_OPTIONS (kOOTextureMinFilterLinear | kOOTextureMagFilterLinear | kOOTextureRepeatS | kOOTextureNoShrink)
61 kRandomBufferSize = 128
78- (id) initWithCacheKey:(NSString *)cacheKey seed:(
RANROTSeed)seed;
80- (void) completeWithData:(
void *)data width:(
unsigned)width height:(
unsigned)height;
99- (void) completeWithData:(
void *)data width:(
unsigned)width height:(
unsigned)height;
106@interface OOPlanetTextureGenerator (Private)
108- (NSString *) cacheKeyForType:(NSString *)type;
109- (OOPlanetNormalMapGenerator *) normalMapGenerator;
110- (OOPlanetAtmosphereGenerator *) atmosphereGenerator;
113- (void) dumpNoiseBuffer:(
float *)noise;
123static float QFactor(
float *accbuffer,
int x,
int y,
unsigned width,
float polar_y_value,
float bias,
float polar_y);
124static float GetQ(
float *qbuffer,
int x,
int y,
unsigned width,
unsigned height,
unsigned widthMask,
unsigned heightMask);
127static float BlendAlpha(
float fraction,
float a,
float b);
135 kPlanetScale256x256 = 1,
137 kPlanetScale1024x1024,
138 kPlanetScale2048x2048,
139 kPlanetScale4096x4096,
141 kPlanetScaleReducedDetail = kPlanetScale512x512,
142 kPlanetScaleFullDetail = kPlanetScale1024x1024,
143 kPlanetScaleExtraDetail = kPlanetScale2048x2048
149- (id) initWithPlanetInfo:(NSDictionary *)planetInfo
151 OOLog(
@"texture.planet.generate",
@"%@",
@"Initialising planetary generator");
154 if ((
self = [super initWithPath:[NSString stringWithFormat:
@"OOPlanetTexture@%p",
self] options:
kOOTextureAllowCubeMap]))
156 OOLog(
@"texture.planet.generate",
@"Extracting parameters for generator %@",
self);
158 _info.landFraction = OOClamp_0_1_f([planetInfo oo_floatForKey:
@"land_fraction" defaultValue:0.3]);
159 _info.polarFraction = OOClamp_0_1_f([planetInfo oo_floatForKey:
@"polar_fraction" defaultValue:0.05]);
164 [[planetInfo objectForKey:@"noise_map_seed"] getValue:&_info.seed];
165 if ([planetInfo objectForKey:
@"cloud_alpha"])
167 OOLog(
@"texture.planet.generate",
@"%@",
@"Extracting atmosphere parameters");
169 _info.cloudAlpha = [planetInfo oo_floatForKey:@"cloud_alpha" defaultValue:1.0f];
170 _info.cloudFraction = OOClamp_0_1_f([planetInfo oo_floatForKey:
@"cloud_fraction" defaultValue:0.3]);
177#ifndef TEXGEN_TEST_RIG
178 if (detailLevel <
DETAIL_LEVEL_SHADERS || [planetInfo oo_boolForKey:
@"isMiniature" defaultValue:NO])
180 _planetScale = kPlanetScaleReducedDetail;
184 _planetScale = kPlanetScaleFullDetail;
188 _planetScale = kPlanetScaleExtraDetail;
191 _planetScale = kPlanetScale4096x4096;
193 _info.perlin3d = [planetInfo oo_boolForKey:@"perlin_3d" defaultValue:detailLevel > DETAIL_LEVEL_SHADERS];
194 _info.planetAspectRatio = _info.perlin3d ? 2 : 1;
195 _info.planetScaleOffset = 8 - _info.planetAspectRatio;
202+ (
OOTexture *) planetTextureWithInfo:(NSDictionary *)planetInfo
206 if (generator !=
nil)
216+ (BOOL) generatePlanetTexture:(
OOTexture **)texture andAtmosphere:(
OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo
218 NSParameterAssert(texture != NULL);
221 if (diffuseGen ==
nil)
return NO;
223 OOPlanetAtmosphereGenerator *atmoGen = [diffuseGen atmosphereGenerator];
224 if (atmoGen ==
nil)
return NO;
227 if (*atmosphere ==
nil)
return NO;
231 return *texture !=
nil;
235+ (BOOL) generatePlanetTexture:(
OOTexture **)texture secondaryTexture:(
OOTexture **)secondaryTexture withInfo:(NSDictionary *)planetInfo
237 NSParameterAssert(texture != NULL);
242 if (diffuseGen ==
nil)
return NO;
244 if (secondaryTexture != NULL)
246 OOPlanetNormalMapGenerator *normalGen = [diffuseGen normalMapGenerator];
247 if (normalGen ==
nil)
return NO;
250 if (*secondaryTexture ==
nil)
return NO;
251 enqueue = [normalGen enqueued];
256 return *texture !=
nil;
260+ (BOOL) generatePlanetTexture:(
OOTexture **)texture secondaryTexture:(
OOTexture **)secondaryTexture andAtmosphere:(
OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo
262 NSParameterAssert(texture != NULL);
267 if (diffuseGen ==
nil)
return NO;
269 if (secondaryTexture != NULL)
271 OOPlanetNormalMapGenerator *normalGen = [diffuseGen normalMapGenerator];
272 if (normalGen ==
nil)
return NO;
275 if (*secondaryTexture ==
nil)
return NO;
276 enqueue = [normalGen enqueued];
279 OOPlanetAtmosphereGenerator *atmoGen = [diffuseGen atmosphereGenerator];
280 if (atmoGen ==
nil)
return NO;
283 if (*atmosphere ==
nil)
285 if (secondaryTexture != NULL) {
286 *secondaryTexture =
nil;
290 enqueue = enqueue || [atmoGen enqueued];
292 OOLog(
@"texture.planet.generate",
@"Generator %@ has atmosphere %@",diffuseGen,*atmosphere);
295 return *texture !=
nil;
308- (NSString *) descriptionComponents
310 return [NSString stringWithFormat:@"seed: %u,%u land: %g", _info.seed.high, _info.seed.low, _info.landFraction];
314- (uint32_t) textureOptions
316 return PLANET_TEXTURE_OPTIONS;
320- (NSString *) cacheKey
322 NSString *type =(_nMapGenerator ==
nil) ?
@"diffuse-baked" :
@"diffuse-raw";
323 if (_atmoGenerator !=
nil) type = [NSString stringWithFormat:@"%@-atmo", type];
324 return [
self cacheKeyForType:type];
328- (NSString *) cacheKeyForType:(NSString *)type
330 return [NSString stringWithFormat:@"OOPlanetTextureGenerator-%@@%u\n%u,%u/%g/%u,%u/%f,%f,%f/%f,%f,%f/%f,%f,%f/%f,%f,%f",
332 _info.width, _info.height, _info.landFraction, _info.seed.high, _info.seed.low,
333 _info.landColor.r, _info.landColor.g, _info.landColor.b,
334 _info.seaColor.r, _info.seaColor.g, _info.seaColor.b,
335 _info.paleLandColor.r, _info.paleLandColor.g, _info.paleLandColor.b,
336 _info.polarSeaColor.r, _info.polarSeaColor.g, _info.polarSeaColor.b];
340- (OOPlanetNormalMapGenerator *) normalMapGenerator
342 if (_nMapGenerator ==
nil)
344 _nMapGenerator = [[OOPlanetNormalMapGenerator alloc] initWithCacheKey:[
self cacheKeyForType:@"normal"] seed:_info.seed];
346 return _nMapGenerator;
350- (OOPlanetAtmosphereGenerator *) atmosphereGenerator
352 if (_atmoGenerator ==
nil)
354 _atmoGenerator = [[OOPlanetAtmosphereGenerator alloc] initWithCacheKey:[
self cacheKeyForType:@"atmo"] seed:_info.seed andParent:self];
356 return _atmoGenerator;
360- (BOOL)getResult:(
OOPixMap *)outData
362 width:(uint32_t *)outWidth
363 height:(uint32_t *)outHeight
369 OOLog(
@"texture.planet.generate.wait",
@"%s generator %@",
"Waiting for",
self);
372 BOOL result = [
super getResult:outData format:outFormat originalWidth:outWidth originalHeight:outHeight];
376 OOLog(
@"texture.planet.generate.dequeue",
@"%s generator %@", result ?
"Dequeued" :
"Failed to dequeue",
self);
380 OOLog(
@"texture.planet.generate.dequeue",
@"%s generator %@ without waiting.", result ?
"Dequeued" :
"Failed to dequeue",
self);
389 OOLog(
@"texture.planet.generate.begin",
@"Started generator %@",
self);
392 BOOL generateNormalMap = (_nMapGenerator !=
nil);
393 BOOL generateAtmosphere = (_atmoGenerator !=
nil);
395 uint8_t *buffer = NULL, *px = NULL;
396 uint8_t *nBuffer = NULL, *npx = NULL;
397 uint8_t *aBuffer = NULL, *apx = NULL;
398 float *randomBuffer = NULL;
400 _height = _info.height = 1 << (_planetScale + _info.planetScaleOffset);
401 _width = _info.width = _height * _info.planetAspectRatio;
403#define FAIL_IF(cond) do { if (EXPECT_NOT(cond)) goto END; } while (0)
404#define FAIL_IF_NULL(x) FAIL_IF((x) == NULL)
406 buffer = malloc(4 * _width * _height);
407 FAIL_IF_NULL(buffer);
410 if (generateNormalMap)
412 nBuffer = malloc(4 * _width * _height);
413 FAIL_IF_NULL(nBuffer);
417 if (generateAtmosphere)
419 aBuffer = malloc(4 * _width * _height);
420 FAIL_IF_NULL(aBuffer);
424 FAIL_IF(!FillFBMBuffer(&_info));
426 [
self dumpNoiseBuffer:_info.fbmBuffer];
429 float paleClouds = (_info.cloudFraction * _info.fbmBuffer[0] < 1.0f - _info.cloudFraction) ? 0.0f : 1.0f;
430 float poleValue = (_info.landFraction > 0.5f) ? 0.5f * _info.landFraction : 0.0f;
431 float seaBias = _info.landFraction - 1.0f;
433 _info.paleSeaColor =
Blend(0.35f, _info.polarSeaColor,
Blend(0.7f, _info.seaColor, _info.landColor));
434 float normalScale = (1 << _planetScale)
437 * [[NSUserDefaults standardUserDefaults] oo_floatForKey:
@"p3dnsf" defaultValue:1.0f]
440 if (!generateNormalMap) normalScale *= 3.0f;
443 _info.deepSeaColor =
Blend(0.85f, _info.seaColor, (
FloatRGB){ 0, 0, 0 });
448 float q, yN, yS, yW, yE, nearPole;
450 float rHeight = 1.0f / _height;
451 float fy, fHeight = _height;
453 SetMixConstants(&_info, 1.0f-_info.polarFraction);
456 _info.qBuffer = malloc(_width * _height *
sizeof (
float));
457 FAIL_IF_NULL(_info.qBuffer);
459 for (
y = (
int)_height - 1, fy = (
float)
y;
y >=0;
y--, fy--)
461 nearPole = (2.0f * fy - fHeight) * rHeight;
462 nearPole *= nearPole;
464 for (
x = (
int)_width - 1;
x >=0;
x--)
466 _info.qBuffer[y * _width + x] = QFactor(_info.fbmBuffer,
x,
y, _width, poleValue, seaBias, nearPole);
471 float cloudFraction = _info.cloudFraction;
472 unsigned widthMask = _width - 1;
473 unsigned heightMask = _height - 1;
475 for (
y = (
int)_height - 1, fy = (
float)
y;
y >= 0;
y--, fy--)
477 nearPole = (2.0f * fy - fHeight) * rHeight;
478 nearPole *= nearPole;
480 for (
x = (
int)_width - 1;
x >= 0;
x--)
482 q = _info.qBuffer[y * _width + x];
483 yN = GetQ(_info.qBuffer,
x,
y - 1, _width, _height, widthMask, heightMask);
484 yS = GetQ(_info.qBuffer,
x,
y + 1, _width, _height, widthMask, heightMask);
485 yW = GetQ(_info.qBuffer,
x - 1,
y, _width, _height, widthMask, heightMask);
486 yE = GetQ(_info.qBuffer,
x + 1,
y, _width, _height, widthMask, heightMask);
488 color = PlanetMix(&_info, q, nearPole);
490 norm = vector_normal(make_vector(normalScale * (yE - yW), normalScale * (yN - yS), 1.0f));
491 if (generateNormalMap)
499 *npx++ = 127.5f * (norm.
y + 1.0f);
500 *npx++ = 127.5f * (-norm.
x + 1.0f);
501 *npx++ = 127.5f * (norm.z + 1.0f);
503 *npx++ = 255.0f * color.a;
515 shade += color.a - color.a * shade;
518 *px++ = 255.0f * color.r * shade;
519 *px++ = 255.0f * color.g * shade;
520 *px++ = 255.0f * color.b * shade;
524 if (generateAtmosphere)
526 q = QFactor(_info.fbmBuffer,
x,
y, _width, paleClouds, cloudFraction, nearPole);
527 color = CloudMix(&_info, q, nearPole);
528 *apx++ = 255.0f * color.r;
529 *apx++ = 255.0f * color.g;
530 *apx++ = 255.0f * color.b;
531 *apx++ = 255.0f * color.a * _info.cloudAlpha;
540 FREE(_info.fbmBuffer);
546 if (generateNormalMap) [_nMapGenerator completeWithData:nBuffer width:_width height:_height];
547 if (generateAtmosphere) [_atmoGenerator completeWithData:aBuffer width:_width height:_height];
558 OOLog(
@"texture.planet.generate.complete",
@"Completed generator %@ %@successfully",
self, success ?
@"" :
@"un");
563 NSString *diffuseName = [NSString stringWithFormat:@"planet-%u-%u-diffuse-new", _info.seed.high, _info.seed.low];
564 NSString *lightsName = [NSString stringWithFormat:@"planet-%u-%u-lights-new", _info.seed.high, _info.seed.low];
566 [[UNIVERSE gameView] dumpRGBAToRGBFileNamed:diffuseName
567 andGrayFileNamed:lightsName
571 rowBytes:_width * 4];
579- (void) dumpNoiseBuffer:(
float *)noise
581 NSString *noiseName = [NSString stringWithFormat:@"planet-%u-%u-noise-new", _info.seed.high, _info.seed.low];
583 uint8_t *noisePx = malloc(_width * _height);
585 for (
y = 0;
y < _height;
y++)
587 for (
x = 0;
x < _width;
x++)
589 noisePx[y * _width + x] = 255.0f * noise[y * _width + x];
593 [[UNIVERSE gameView] dumpGrayToFileNamed:noiseName
606OOINLINE float Lerp(
float v0,
float v1,
float fraction)
609 return v0 + fraction * (v1 - v0);
617 Lerp(b.
r, a.
r, fraction),
618 Lerp(b.
g, a.
g, fraction),
619 Lerp(b.
b, a.
b, fraction)
624static float BlendAlpha(
float fraction,
float a,
float b)
626 return Lerp(b, a, fraction);
635#define AIR_ALPHA (0.05f)
636#define CLOUD_ALPHA (2.0f)
638#define POLAR_BOUNDARY (0.33f)
639#define CLOUD_BOUNDARY (0.5f)
640#define RECIP_CLOUD_BOUNDARY (1.0f / CLOUD_BOUNDARY)
643 float alpha = info->
cloudAlpha, portion = 0.0f;
645 q -= CLOUD_BOUNDARY * 0.5f;
647 if (nearPole > POLAR_BOUNDARY)
649 portion = nearPole > POLAR_BOUNDARY + 0.2f ? 1.0f : (nearPole - POLAR_BOUNDARY) * 5.0f;
652 portion = nearPole > POLAR_BOUNDARY + 0.625f ? 1.0f : (nearPole - POLAR_BOUNDARY) * 1.6f;
657 if (q >= -CLOUD_BOUNDARY)
659 alpha *= BlendAlpha(-q * 0.5f * RECIP_CLOUD_BOUNDARY + 0.5f,
CLOUD_ALPHA, AIR_ALPHA);
668 if (q < CLOUD_BOUNDARY)
670 alpha *= BlendAlpha( q * 0.5f * RECIP_CLOUD_BOUNDARY + 0.5f, AIR_ALPHA,
CLOUD_ALPHA);
678 alpha *= BlendAlpha(portion, 0.6f, 1.0f);
684 return (
FloatRGBA){ cloudColor.
r, cloudColor.
g, cloudColor.
b, alpha };
690#define RECIP_COASTLINE_PORTION (160.0f)
691#define COASTLINE_PORTION (1.0f / RECIP_COASTLINE_PORTION)
692#define SHALLOWS (2.0f * COASTLINE_PORTION)
693#define RECIP_SHALLOWS (1.0f / SHALLOWS)
695#define DEEPS (40.0f * COASTLINE_PORTION)
696#define RECIP_DEEPS (1.0f / DEEPS)
698 const FloatRGB white = { 1.0f, 1.0f, 1.0f };
702 float specular = 0.01f;
718 specular = Lerp(1.0f, 0.85f, -q);
721 else if (q < COASTLINE_PORTION)
724 specular = q * RECIP_COASTLINE_PORTION;
726 specular = 1.0f - specular;
733 else if (q > info->
mix_hi)
745 float phi = info->
mix_polarCap + info->mix_polarCap - nearPole;
749 specular = q > phi + 0.02f ? 1.0f : 0.2f + (q - phi) * 40.0f;
752 specular = specular * 0.5f;
756 return (
FloatRGBA){ diffuse.
r, diffuse.
g, diffuse.
b, specular };
762 OOColor *color = [dictionary objectForKey:key];
763 NSCAssert1([color isKindOfClass:[
OOColor class]],
@"Expected OOColor, got %@", [color
class]);
771 return 3.0f * q * q - 2.0f * q * q * q;
783OOINLINE int32_t fast_floor(
double val)
785 val += 68719476736.0 * 1.5;
786 return (((int32_t*)&val)[iman_] >> 16);
796 NSCParameterAssert(info != NULL);
804 GenerateFBMNoise(info);
808 GenerateFBMNoise3D(info);
821 kPermutationCount = 1 << 10,
822 kPermutationMask = kPermutationCount - 1,
833static const Vector kGradients[kGradientCount] =
849static const uint8_t kGradients[kGradientCount][3] =
874OOINLINE float TDot3(
const uint8_t grad[3],
float x,
float y,
float z)
876 float xt[3] = { -
x, 0.0f,
x };
877 float yt[3] = { -
y, 0.0f,
y };
878 float zt[3] = { -z, 0.0f, z };
880 return xt[grad[0]] + yt[grad[1]] + zt[grad[2]];
891 float fx = floor(p.x);
892 float fy = floor(p.y);
893 float fz = floor(p.z);
902#define PERM(v) permutations[(v) & kPermutationMask]
904 unsigned PZ0 = PERM(Z);
905 unsigned PZ1 = PERM(Z + 1);
907 unsigned PY0Z0 = PERM(Y + PZ0);
908 unsigned PY1Z0 = PERM(Y + 1 + PZ0);
909 unsigned PY0Z1 = PERM(Y + PZ1);
910 unsigned PY1Z1 = PERM(Y + 1 + PZ1);
912 unsigned gi000 = PERM(X + PY0Z0);
913 unsigned gi010 = PERM(X + PY1Z0);
914 unsigned gi100 = PERM(X + 1 + PY0Z0);
915 unsigned gi110 = PERM(X + 1 + PY1Z0);
916 unsigned gi001 = PERM(X + PY0Z1);
917 unsigned gi011 = PERM(X + PY1Z1);
918 unsigned gi101 = PERM(X + 1 + PY0Z1);
919 unsigned gi111 = PERM(X + 1 + PY1Z1);
925#define DOT3(idx, x_, y_, z_) dot_product(kGradients[(idx) % kGradientCount], (Vector){ (x_), (y_), (z_) })
927#define DOT3(idx, x_, y_, z_) TDot3(kGradients[(idx) % kGradientCount], (x_), (y_), (z_))
933 float n000 = DOT3(gi000,
x ,
y , z );
934 float n010 = DOT3(gi010,
x , y1, z );
935 float n100 = DOT3(gi100, x1,
y , z );
936 float n110 = DOT3(gi110, x1, y1, z );
937 float n001 = DOT3(gi001,
x ,
y , z1);
938 float n011 = DOT3(gi011,
x , y1, z1);
939 float n101 = DOT3(gi101, x1,
y , z1);
940 float n111 = DOT3(gi111, x1, y1, z1);
945 float u = Hermite(
x);
946 float v = Hermite(
y);
947 float w = Hermite(z);
950 float nx00 = Lerp(n000, n100, u);
951 float nx01 = Lerp(n001, n101, u);
952 float nx10 = Lerp(n010, n110, u);
953 float nx11 = Lerp(n011, n111, u);
955 float nxy0 = Lerp(nx00, nx10, v);
956 float nxy1 = Lerp(nx01, nx11, v);
958 float nxyz = Lerp(nxy0, nxy1, w);
967 uint16_t *perms = malloc(
sizeof *info->
permutations * kPermutationCount);
972 for (n = 1; n < kPermutationCount; n++)
986 FAIL_IF(!MakePermutationTable(info));
990 float dlon = 2.0f *
M_PI / width;
991 float dlat =
M_PI / height;
994 for (
y = 0, lat = -
M_PI_2;
y < height;
y++, lat += dlat)
996 float las = sin(lat);
997 float lac = cos(lat);
999 for (
x = 0, lon = -
M_PI;
x < width;
x++, lon += dlon)
1003 float los = sin(lon);
1004 float loc = cos(lon);
1015 unsigned octaveMask = 4;
1016 float octave = octaveMask;
1021 while ((octaveMask + 1) < height)
1023 Vector ps = vector_multiply_scalar(p, octave);
1024 sum += scale * SampleNoise3D(info, ps);
1027 octaveMask = (octaveMask << 1) | 1;
1032 p = vector_multiply_scalar(p, 4.0f);
1033 float sum = 0.5f * SampleNoise3D(info, p);
1048static void FillRandomBuffer(
float *randomBuffer,
RANROTSeed seed)
1050 unsigned i, len = kRandomBufferSize * kRandomBufferSize;
1051 for (i = 0; i < len; i++)
1058static void AddNoise(
OOPlanetTextureGeneratorInfo *info,
float *randomBuffer,
float octave,
unsigned octaveMask,
float scale,
float *qxBuffer,
int *ixBuffer)
1061 unsigned width = info->
width, height = info->
height;
1063 float rr = octave / width;
1064 float fx, fy, qx, qy, rix, rjx, rfinal;
1067 for (fy = 0,
y = 0;
y < height; fy++,
y++)
1070 iy = fast_floor(qy);
1071 jy = (iy + 1) & octaveMask;
1072 qy = Hermite(qy - iy);
1073 iy &= (kRandomBufferSize - 1);
1074 jy &= (kRandomBufferSize - 1);
1076 for (fx = 0,
x = 0;
x < width; fx++,
x++)
1082 ix = fast_floor(qx);
1084 ix &= (kRandomBufferSize - 1);
1086 qxBuffer[x] = Hermite(qx);
1095 jx = (ix + 1) & octaveMask;
1096 jx &= (kRandomBufferSize - 1);
1098 rix = Lerp(randomBuffer[iy * kRandomBufferSize + ix], randomBuffer[iy * kRandomBufferSize + jx], qx);
1099 rjx = Lerp(randomBuffer[jy * kRandomBufferSize + ix], randomBuffer[jy * kRandomBufferSize + jx], qx);
1100 rfinal = Lerp(rix, rjx, qy);
1102 *dst++ += scale * rfinal;
1111 size_t randomBufferSize = kRandomBufferSize * kRandomBufferSize *
sizeof (float);
1112 size_t qxBufferSize = info->
width *
sizeof (float);
1113 size_t ixBufferSize = info->
width *
sizeof (
int);
1114 char *sharedBuffer = malloc(randomBufferSize + qxBufferSize + ixBufferSize);
1115 if (sharedBuffer == NULL)
return NO;
1117 float *randomBuffer = (
float *)sharedBuffer;
1118 float *qxBuffer = (
float *)(sharedBuffer + randomBufferSize);
1119 int *ixBuffer = (
int *)(sharedBuffer + randomBufferSize + qxBufferSize);
1122 FillRandomBuffer(randomBuffer, info->
seed);
1125 unsigned height = info->
height;
1127 float octave = octaveMask;
1131 while ((octaveMask + 1) < height)
1133 AddNoise(info, randomBuffer, octave, octaveMask, scale, qxBuffer, ixBuffer);
1135 octaveMask = (octaveMask << 1) | 1;
1145static float QFactor(
float *accbuffer,
int x,
int y,
unsigned width,
float polar_y_value,
float bias,
float polar_y)
1147 float q = accbuffer[y * width + x];
1151 q = q * (1.0f - polar_y) + polar_y * polar_y_value;
1157static float GetQ(
float *qbuffer,
int x,
int y,
unsigned width,
unsigned height,
unsigned widthMask,
unsigned heightMask)
1167 if (
y & height) {
y = (
y ^ heightMask) & heightMask;
x += width >> 1; }
1170 return qbuffer[y * width + x];
1178 info->
mix_ih = 1.0f / (1.0f - info->mix_hi);
1179 info->
mix_polarCap = temperatureFraction * (0.28f + 0.24f * info->landFraction);
1183@implementation OOPlanetNormalMapGenerator
1185- (id) initWithCacheKey:(NSString *)cacheKey seed:(
RANROTSeed)seed
1188 if ((
self = [super initWithPath:[NSString stringWithFormat:
@"OOPlanetNormalTexture@%p",
self] options:
kOOTextureAllowCubeMap]))
1191 _cacheKey = [cacheKey copy];
1206- (NSString *) cacheKey
1212- (uint32_t) textureOptions
1214 return PLANET_TEXTURE_OPTIONS;
1242- (void) completeWithData:(
void *)data_ width:(
unsigned)width_ height:(
unsigned)height_
1253 NSString *normalName = [NSString stringWithFormat:@"planet-%u-%u-normal-new", _seed.high, _seed.low];
1254 NSString *specularName = [NSString stringWithFormat:@"planet-%u-%u-specular-new", _seed.high, _seed.low];
1256 [[UNIVERSE gameView] dumpRGBAToRGBFileNamed:normalName
1257 andGrayFileNamed:specularName
1261 rowBytes:_width * 4];
1268@implementation OOPlanetAtmosphereGenerator
1272 OOLog(
@"texture.planet.generate",
@"Initialising atmosphere generator %@",cacheKey);
1274 if ((
self = [super initWithPath:[NSString stringWithFormat:
@"OOPlanetAtmoTexture@%p",
self] options:
kOOTextureAllowCubeMap]))
1276 _cacheKey = [cacheKey copy];
1278 _parent = [parent retain];
1293- (NSString *) cacheKey
1299- (uint32_t) textureOptions
1301 return PLANET_TEXTURE_OPTIONS;
1333- (BOOL) getResult:(
OOPixMap *)result
1335 originalWidth:(uint32_t *)outWidth
1336 originalHeight:(uint32_t *)outHeight
1343 return [
super getResult:result
1345 originalWidth:outWidth
1346 originalHeight:outHeight];
1350- (void) completeWithData:(
void *)data_ width:(
unsigned)width_ height:(
unsigned)height_
1352 OOLog(
@"texture.planet.generate",
@"%@",
@"Completing atmosphere generator");
1363 NSString *rgbName = [NSString stringWithFormat:@"planet-%u-%u-atmosphere-rgb-new", _seed.high, _seed.low];
1364 NSString *alphaName = [NSString stringWithFormat:@"planet-%u-%u-atmosphere-alpha-new", _seed.high, _seed.low];
1366 [[UNIVERSE gameView] dumpRGBAToRGBFileNamed:rgbName
1367 andGrayFileNamed:alphaName
1371 rowBytes:_width * 4];
#define OOLog(class, format,...)
const Vector kBasisZVector
static FloatRGB FloatRGBFromDictColor(NSDictionary *dictionary, NSString *key)
static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b)
void waitForTaskToComplete:(id< OOAsyncWorkTask > task)
OOAsyncWorkManager * sharedAsyncWorkManager()
id textureWithGenerator:(OOTextureGenerator *generator)
id textureWithGenerator:enqueue:(OOTextureGenerator *generator,[enqueue] BOOL enqueue)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
float randfWithSeed(RANROTSeed *ioSeed)
unsigned RanrotWithSeed(RANROTSeed *ioSeed)
unsigned planetAspectRatio