- yet more go-faster tweaks to the texture generator.

- integrated the previously separate atmosphere generator inside OOPlanetTextureGenerator, to avoid noise generator overheads.
- added NEW_ATMOSPHERE compile-time switch to OOPlanetEntity.

- tidying up of contract market generators: while they're still slow, some dead code was removed.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2918 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Marc 2009-12-30 09:17:01 +00:00
parent c0b6f16429
commit bb93c112da
15 changed files with 444 additions and 556 deletions

View File

@ -181,7 +181,6 @@ OOLITE_GRAPHICS_MATERIAL_FILES = \
OOMaterial.m \
OONullTexture.m \
OOPlanetTextureGenerator.m \
OOCloudTextureGenerator.m \
OOPNGTextureLoader.m \
OOShaderMaterial.m \
OOShaderProgram.m \

View File

@ -696,8 +696,6 @@
2B13C521105D343900AF4A7B /* oolite-nova-system.png in Copy Images */ = {isa = PBXBuildFile; fileRef = 2B13C51E105D342D00AF4A7B /* oolite-nova-system.png */; };
2B4CDFEC107B3D8400526C98 /* OOJSManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B4CDFEA107B3D8400526C98 /* OOJSManifest.h */; };
2B4CDFED107B3D8400526C98 /* OOJSManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B4CDFEB107B3D8400526C98 /* OOJSManifest.m */; };
2B6EB2DB10D03E08007EAC20 /* OOCloudTextureGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B6EB2D910D03E08007EAC20 /* OOCloudTextureGenerator.h */; };
2B6EB2DC10D03E08007EAC20 /* OOCloudTextureGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B6EB2DA10D03E08007EAC20 /* OOCloudTextureGenerator.m */; };
2B9A1089105D526200EE2AE6 /* javascript-errors.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2B9A1088105D526200EE2AE6 /* javascript-errors.plist */; };
2B9A108A105D527C00EE2AE6 /* javascript-errors.plist in Copy Config */ = {isa = PBXBuildFile; fileRef = 2B9A1088105D526200EE2AE6 /* javascript-errors.plist */; };
/* End PBXBuildFile section */
@ -1813,8 +1811,6 @@
2B13C51E105D342D00AF4A7B /* oolite-nova-system.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "oolite-nova-system.png"; sourceTree = "<group>"; };
2B4CDFEA107B3D8400526C98 /* OOJSManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSManifest.h; sourceTree = "<group>"; };
2B4CDFEB107B3D8400526C98 /* OOJSManifest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSManifest.m; sourceTree = "<group>"; };
2B6EB2D910D03E08007EAC20 /* OOCloudTextureGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOCloudTextureGenerator.h; sourceTree = "<group>"; };
2B6EB2DA10D03E08007EAC20 /* OOCloudTextureGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOCloudTextureGenerator.m; sourceTree = "<group>"; };
2B9A1088105D526200EE2AE6 /* javascript-errors.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = "javascript-errors.plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -2481,8 +2477,6 @@
1A71E85D0BCE8A5500CD5C13 /* Textures */ = {
isa = PBXGroup;
children = (
2B6EB2D910D03E08007EAC20 /* OOCloudTextureGenerator.h */,
2B6EB2DA10D03E08007EAC20 /* OOCloudTextureGenerator.m */,
1A26D0E10BCF9D3B0073F257 /* OOTexture.h */,
1A26D0E00BCF9D3B0073F257 /* OOTexture.m */,
1A8BB8E80E8311F900122974 /* OONullTexture.h */,
@ -3176,7 +3170,6 @@
1AA7FE2D10C2F2070058FBED /* OOTextureGenerator.h in Headers */,
1AA7FE3410C2F26A0058FBED /* OOPlanetTextureGenerator.h in Headers */,
1ADA564810CD68D800E891B8 /* OOStellarBody.h in Headers */,
2B6EB2DB10D03E08007EAC20 /* OOCloudTextureGenerator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3548,7 +3541,6 @@
1AA7FDDD10C2DC800058FBED /* OOSunEntity.m in Sources */,
1AA7FE2E10C2F2070058FBED /* OOTextureGenerator.m in Sources */,
1AA7FE3510C2F26A0058FBED /* OOPlanetTextureGenerator.m in Sources */,
2B6EB2DC10D03E08007EAC20 /* OOCloudTextureGenerator.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -50,7 +50,6 @@ MA 02110-1301, USA.
OOTimeDelta _shuttleLaunchInterval;
NSDictionary *_materialParameters;
NSDictionary *_atmosphereParameters;
}
- (id) initAsMainPlanetForSystemSeed:(Random_Seed)seed;

View File

@ -27,6 +27,7 @@ MA 02110-1301, USA.
#if NEW_PLANETS
#define SHADY_PLANETS !NO_SHADERS
#define NEW_ATMOSPHERE 0
#import "OOPlanetDrawable.h"
@ -42,7 +43,6 @@ MA 02110-1301, USA.
#import "OOCollectionExtractors.h"
#import "OOPlanetTextureGenerator.h"
#import "OOCloudTextureGenerator.h"
#import "OOSingleTextureMaterial.h"
#import "OOShaderMaterial.h"
@ -108,11 +108,32 @@ MA 02110-1301, USA.
_planetDrawable = [[OOPlanetDrawable alloc] init];
// Load material parameters.
// Load material parameters, including atmosphere.
RANROTSeed planetNoiseSeed = RANROTGetFullSeed();
[planetInfo setObject:[NSValue valueWithBytes:&planetNoiseSeed objCType:@encode(RANROTSeed)] forKey:@"noise_map_seed"];
[self setUpLandParametersWithSourceInfo:dict targetInfo:planetInfo];
_materialParameters = [planetInfo dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"land_fraction", @"land_color", @"sea_color", @"polar_land_color", @"polar_sea_color", @"noise_map_seed", @"economy", nil]];
#if NEW_ATMOSPHERE
if (atmosphere)
{
_atmosphereDrawable = [[OOPlanetDrawable atmosphereWithRadius:collision_radius + ATMOSPHERE_DEPTH] retain];
// convert the atmosphere settings to generic 'material parameters'
percent_land = 100 - [dict oo_intForKey:@"percent_cloud" defaultValue:100 - (3 + (gen_rnd_number() & 31)+(gen_rnd_number() & 31))];
[planetInfo setObject:[NSNumber numberWithFloat:0.01 * percent_land] forKey:@"cloud_fraction"];
[self setUpAtmosphereParametersWithSourceInfo:dict targetInfo:planetInfo];
_materialParameters = [planetInfo dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"cloud_fraction", @"air_color", @"polar_air_color", @"cloud_color", @"polar_cloud_color", @"cloud_alpha",
@"land_fraction", @"land_color", @"sea_color", @"polar_land_color", @"polar_sea_color", @"noise_map_seed", @"economy", nil]];
}
else
#else
// differentiate between normal planets and moons.
if (atmosphere) _atmosphereDrawable = [[OOPlanetDrawable atmosphereWithRadius:collision_radius + ATMOSPHERE_DEPTH] retain];
#endif
{
_materialParameters = [planetInfo dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"land_fraction", @"land_color", @"sea_color", @"polar_land_color", @"polar_sea_color", @"noise_map_seed", @"economy", nil]];
}
[_materialParameters retain];
NSString *textureName = [dict oo_stringForKey:@"texture"];
@ -138,30 +159,6 @@ MA 02110-1301, USA.
_rotationalVelocity *= [planetInfo oo_floatForKey:@"rotation_speed_factor" defaultValue:1.0f];
}
if (atmosphere)
{
#if 1
_atmosphereDrawable = [[OOPlanetDrawable atmosphereWithRadius:collision_radius + ATMOSPHERE_DEPTH] retain];
NSMutableDictionary *atmosphereInfo = [NSMutableDictionary dictionaryWithCapacity:6];
// convert the atmosphere settings to generic 'material parameters'
percent_land = 100 - [dict oo_intForKey:@"percent_cloud" defaultValue:100 - (3 + (gen_rnd_number() & 31)+(gen_rnd_number() & 31))];
[atmosphereInfo setObject:[NSNumber numberWithFloat:0.01 * percent_land] forKey:@"land_fraction"];
[atmosphereInfo setObject:[planetInfo objectForKey:@"noise_map_seed"] forKey:@"noise_map_seed"];
[self setUpAtmosphereParametersWithSourceInfo:dict targetInfo:atmosphereInfo];
_atmosphereParameters = [atmosphereInfo copy];
//[atmosphereInfo autorelease];
OOTexture *atmosphereTexture = [OOCloudTextureGenerator cloudTextureWithInfo:_atmosphereParameters];
OOSingleTextureMaterial *material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:atmosphereTexture configuration:nil];
[_atmosphereDrawable setMaterial:material];
[material release];
#endif
}
// set energy
energy = collision_radius * 1000.0;
@ -254,7 +251,7 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
ScanVectorFromString([sourceInfo oo_stringForKey:@"land_hsb_color"], &landHSB);
ScanVectorFromString([sourceInfo oo_stringForKey:@"sea_hsb_color"], &seaHSB);
// polar areas are brighter but have less color (closer to white)
// polar areas are brighter but have less colour (closer to white)
landPolarHSB = LighterHSBColor(landHSB);
seaPolarHSB = LighterHSBColor(seaHSB);
@ -263,24 +260,18 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
[targetInfo setObject:ColorWithHSBColor(seaHSB) forKey:@"sea_color"];
[targetInfo setObject:ColorWithHSBColor(landPolarHSB) forKey:@"polar_land_color"];
[targetInfo setObject:ColorWithHSBColor(seaPolarHSB) forKey:@"polar_sea_color"];
}
else
{
float cloudAlpha = cloudAlpha = OOClamp_0_1_f([sourceInfo oo_floatForKey:@"cloud_alpha" defaultValue:1.0f]);
[targetInfo setObject:[NSNumber numberWithFloat:cloudAlpha] forKey:@"cloud_alpha"];
#define CLEAR_SKY_ALPHA 0.05
#define CLOUD_ALPHA 0.50
#define POLAR_CLEAR_SKY_ALPHA 0.34
#define POLAR_CLOUD_ALPHA 0.75
color = [OOColor colorWithDescription:[sourceInfo objectForKey:@"cloud_color"]];
if (color != nil) landHSB = HSBColorWithColor(color);
color = [OOColor colorWithDescription:[sourceInfo objectForKey:@"clear_sky_color"]];
if (color != nil) seaHSB = HSBColorWithColor(color);
// polar areas are brighter but have less color (closer to white)
// polar areas are brighter but have less colour (closer to white)
landPolarHSB = LighterHSBColor(landHSB);
seaPolarHSB = LighterHSBColor(seaHSB);
@ -289,11 +280,10 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
color = [OOColor colorWithDescription:[sourceInfo objectForKey:@"polar_clear_sky_color"]];
if (color != nil) seaPolarHSB = HSBColorWithColor(color);
//TODO: rename these keys to something sensible
[targetInfo setObject:ColorWithHSBColorAndAlpha(landHSB, CLEAR_SKY_ALPHA) forKey:@"land_color"];
[targetInfo setObject:ColorWithHSBColorAndAlpha(seaHSB, CLOUD_ALPHA) forKey:@"sea_color"];
[targetInfo setObject:ColorWithHSBColorAndAlpha(landPolarHSB, POLAR_CLEAR_SKY_ALPHA) forKey:@"polar_land_color"];
[targetInfo setObject:ColorWithHSBColorAndAlpha(seaPolarHSB, POLAR_CLOUD_ALPHA) forKey:@"polar_sea_color"];
[targetInfo setObject:ColorWithHSBColor(landHSB) forKey:@"air_color"];
[targetInfo setObject:ColorWithHSBColor(seaHSB) forKey:@"cloud_color"];
[targetInfo setObject:ColorWithHSBColor(landPolarHSB) forKey:@"polar_air_color"];
[targetInfo setObject:ColorWithHSBColor(seaPolarHSB) forKey:@"polar_cloud_color"];
}
}
@ -339,7 +329,6 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
DESTROY(_planetDrawable);
DESTROY(_atmosphereDrawable);
DESTROY(_materialParameters);
DESTROY(_atmosphereParameters);
[super dealloc];
}
@ -408,10 +397,12 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
}
[_planetDrawable renderOpaqueParts];
if (0)//(_atmosphereDrawable != nil)
#if NEW_ATMOSPHERE
if (_atmosphereDrawable != nil)
{
[_atmosphereDrawable renderOpaqueParts];
}
#endif
if ([UNIVERSE wireframeGraphics]) GLDebugWireframeModeOff();
}
@ -477,6 +468,8 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
- (void) setTextureFileName:(NSString *)textureName
{
BOOL isMoon = _atmosphereDrawable == nil;
#if !SHADY_PLANETS
if (textureName != nil)
{
@ -484,8 +477,27 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
}
else
{
OOTexture *texture = [OOPlanetTextureGenerator planetTextureWithInfo:_materialParameters];
OOSingleTextureMaterial *material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:texture configuration:nil];
OOTexture *texture = nil;
OOSingleTextureMaterial *material = nil
if (isMoon)
{
texture = [OOPlanetTextureGenerator planetTextureWithInfo:_materialParameters];
material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:texture configuration:nil];
}
else
{
OOTexture *atmosphere = nil;
[OOPlanetTextureGenerator generatePlanetTexture:&texture
andAtmosphere:&atmosphere
withInfo:_materialParameters];
material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:atmosphere configuration:nil];
[_atmosphereDrawable setMaterial:material];
[material release];
material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:texture configuration:nil];
}
[_planetDrawable setMaterial:material];
[material release];
}
@ -500,7 +512,6 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
#else
const BOOL shadersOn = NO;
#endif
BOOL isMoon = _atmosphereDrawable == nil;
if (textureName != nil)
{
@ -510,9 +521,24 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
}
else
{
[OOPlanetTextureGenerator generatePlanetTexture:&diffuseMap
secondaryTexture:(shaderLevel == SHADERS_FULL) ? &normalMap : NULL
withInfo:_materialParameters];
if (isMoon)
{
[OOPlanetTextureGenerator generatePlanetTexture:&diffuseMap
secondaryTexture:(shaderLevel == SHADERS_FULL) ? &normalMap : NULL
withInfo:_materialParameters];
}
else
{
OOTexture *atmosphere = nil;
[OOPlanetTextureGenerator generatePlanetTexture:&diffuseMap
secondaryTexture:(shaderLevel == SHADERS_FULL) ? &normalMap : NULL
andAtmosphere:&atmosphere
withInfo:_materialParameters];
OOSingleTextureMaterial *material = [[OOSingleTextureMaterial alloc] initWithName:@"dynamic" texture:atmosphere configuration:nil];
[_atmosphereDrawable setMaterial:material];
[material release];
}
if (shadersOn) macros = [materialDefaults oo_dictionaryForKey:isMoon ? @"moon-dynamic-macros" : @"planet-dynamic-macros"];
textureName = @"dynamic";
}

View File

@ -3834,7 +3834,7 @@ static PlayerEntity *sSharedPlayer = nil;
if ([dockedStation localMarket] == nil)
{
[dockedStation initialiseLocalMarketWithSeed:system_seed andRandomFactor:market_rnd];
[dockedStation initialiseLocalMarketWithRandomFactor:market_rnd];
}
NSString *escapepodReport = [self processEscapePods];
@ -6014,7 +6014,7 @@ static NSString *last_outfitting_key=nil;
if ([self isDocked]) station = dockedStation;
else station = [UNIVERSE station];
localMarket = [station localMarket];
if (localMarket == nil) localMarket = [station initialiseLocalMarketWithSeed:system_seed andRandomFactor:market_rnd];
if (localMarket == nil) localMarket = [station initialiseLocalMarketWithRandomFactor:market_rnd];
return localMarket;
}

View File

@ -549,9 +549,9 @@ static NSString * const kOOLogNoteShowShipyardModel = @"script.debug.note.showSh
// set up initial markets if there are none
StationEntity* the_station = [UNIVERSE station];
if (![the_station localPassengers])
[the_station setLocalPassengers:[NSMutableArray arrayWithArray:[UNIVERSE passengersForSystem:system_seed atTime:ship_clock]]];
[the_station setLocalPassengers:[NSMutableArray arrayWithArray:[UNIVERSE passengersForLocalSystemAtTime:ship_clock]]];
if (![the_station localContracts])
[the_station setLocalContracts:[NSMutableArray arrayWithArray:[UNIVERSE contractsForSystem:system_seed atTime:ship_clock]]];
[the_station setLocalContracts:[NSMutableArray arrayWithArray:[UNIVERSE contractsForLocalSystemAtTime:ship_clock]]];
NSMutableArray* passenger_market = [the_station localPassengers];
NSMutableArray* contract_market = [the_station localContracts];

View File

@ -485,7 +485,7 @@
{
NSArray *market = [fileDic oo_arrayForKey:@"localMarket"];
if (market != nil) [dockedStation setLocalMarket:market];
else [dockedStation initialiseLocalMarketWithSeed:system_seed andRandomFactor:market_rnd];
else [dockedStation initialiseLocalMarketWithRandomFactor:market_rnd];
}
[self calculateCurrentCargo];
[UNIVERSE setGalaxy_seed: galaxy_seed andReinit:YES]; // set overridden planet names on long range map

View File

@ -108,9 +108,8 @@ typedef enum
- (NSMutableArray *) localShipyard;
- (void) setLocalShipyard:(NSArray *) some_market;
- (NSMutableArray *) initialiseLocalMarketWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor;
- (NSMutableArray *) initialiseLocalPassengersWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor;
- (NSMutableArray *) initialiseLocalContractsWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor;
- (NSMutableArray *) initialiseLocalMarketWithRandomFactor:(int) random_factor;
- (NSMutableArray *) initialiseMarketWithSeed:(Random_Seed) s_seed andRandomFactor:(int) random_factor;
- (OOTechLevelID) equivalentTechLevel;
- (void) setEquivalentTechLevel:(OOTechLevelID) value;

View File

@ -163,7 +163,13 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
}
- (NSMutableArray *) initialiseLocalMarketWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor
- (NSMutableArray *) initialiseLocalMarketWithRandomFactor:(int) random_factor
{
return [self initialiseMarketWithSeed:[[PlayerEntity sharedPlayer] system_seed] andRandomFactor:random_factor];
}
- (NSMutableArray *) initialiseMarketWithSeed:(Random_Seed) s_seed andRandomFactor:(int) random_factor
{
int rf = (random_factor ^ universalID) & 0xff;
int economy = [[UNIVERSE generateSystemData:s_seed] oo_intForKey:KEY_ECONOMY];
@ -174,24 +180,6 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
}
- (NSMutableArray *) initialiseLocalPassengersWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor
{
if (localPassengers)
[localPassengers release];
localPassengers = [[NSMutableArray alloc] initWithArray:[UNIVERSE passengersForSystem:s_seed atTime:[[[PlayerEntity sharedPlayer] clock_number] intValue]]];
return localPassengers;
}
- (NSMutableArray *) initialiseLocalContractsWithSeed: (Random_Seed) s_seed andRandomFactor: (int) random_factor
{
if (localContracts)
[localContracts release];
localContracts = [[NSMutableArray alloc] initWithArray:[UNIVERSE contractsForSystem:s_seed atTime:[[[PlayerEntity sharedPlayer] clock_number] intValue]]];
return localContracts;
}
- (void) setPlanet:(OOPlanetEntity *)planet_entity
{
if (planet_entity)

View File

@ -1,49 +0,0 @@
/*
OOCloudTextureGenerator.h
Generator for planet diffuse maps.
Oolite
Copyright (C) 2004-2009 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOTextureGenerator.h"
#import "OOMaths.h"
@interface OOCloudTextureGenerator: OOTextureGenerator
{
@private
float _landFraction, _overallAlpha;
FloatRGB _landColor;
FloatRGB _seaColor;
FloatRGB _polarLandColor;
FloatRGB _polarSeaColor;
unsigned _width, _height;
RANROTSeed _seed;
}
- (id) initWithPlanetInfo:(NSDictionary *)planetInfo;
+ (OOTexture *) cloudTextureWithInfo:(NSDictionary *)planetInfo;
//+ (void) generatePlanetTexture:(OOTexture **)texture secondaryTexture:(OOTexture **)secondaryTexture forShaderLevel:(OOShaderSetting)shaderLevel;
@end

View File

@ -1,358 +0,0 @@
/*
OOCloudTextureGenerator.m
Generator for planet diffuse maps.
Oolite
Copyright (C) 2004-2009 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#define DEBUG_DUMP ( 0 && !defined(NDEBUG))
#define DISABLE_SPECULAR ( 1 && DEBUG_DUMP) // No transparency in debug dump to make life easier.
#import "OOCloudTextureGenerator.h"
#import "OOCollectionExtractors.h"
#import "OOColor.h"
#import "OOTexture.h"
#if DEBUG_DUMP
#import "Universe.h"
#import "MyOpenGLView.h"
#endif
enum
{
kNoiseBufferSize = 128
};
static FloatRGB FloatRGBFromDictColor(NSDictionary *dictionary, NSString *key);
static void FillNoiseBuffer(float *noiseBuffer, RANROTSeed seed);
static void AddNoise(float *buffer, unsigned width, unsigned height, unsigned octave, float scale, const float *noiseBuffer);
static float QFactor(float *accbuffer, int x, int y, unsigned width, unsigned height, float polar_y_value, float bias);
static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b);
static FloatRGBA CloudMix(float q, float maxQ, FloatRGB cloudColor, float alpha);
#define PLANET_ASPECT_RATIO 1 // Ideally, aspect ratio would be 2:1 - keeping it as 1:1 for now - Kaks 20091211
#define PLANET_HEIGHT 512
#define PLANET_WIDTH (PLANET_HEIGHT * PLANET_ASPECT_RATIO)
@implementation OOCloudTextureGenerator
- (id) initWithPlanetInfo:(NSDictionary *)planetInfo
{
if ((self = [super init]))
{
_landFraction = OOClamp_0_1_f([planetInfo oo_floatForKey:@"land_fraction" defaultValue:0.3]);
_landColor = FloatRGBFromDictColor(planetInfo, @"land_color");
_seaColor = FloatRGBFromDictColor(planetInfo, @"sea_color");
_polarLandColor = FloatRGBFromDictColor(planetInfo, @"polar_land_color");
_polarSeaColor = FloatRGBFromDictColor(planetInfo, @"polar_sea_color");
[[planetInfo objectForKey:@"noise_map_seed"] getValue:&_seed];
_overallAlpha = [planetInfo oo_floatForKey:@"cloud_alpha" defaultValue:1.0f];
_width = PLANET_WIDTH;
_height = PLANET_HEIGHT;
}
return self;
}
+ (OOTexture *) cloudTextureWithInfo:(NSDictionary *)planetInfo
{
OOTexture *result = nil;
OOCloudTextureGenerator *generator = [[self alloc] initWithPlanetInfo:planetInfo];
if (generator != nil)
{
result = [OOTexture textureWithGenerator:generator];
[generator release];
}
return result;
}
- (NSString *) descriptionComponents
{
return [NSString stringWithFormat:@"seed: %u,%u", _seed.high, _seed.low];
}
- (uint32_t) textureOptions
{
return kOOTextureMinFilterLinear | kOOTextureMagFilterLinear | kOOTextureRepeatS | kOOTextureNoShrink;
}
- (NSString *) cacheKey
{
return [NSString stringWithFormat:@"OOCloudTextureGenerator-base\n\n%u,%u/%g/%u,%u/%f,%f,%f/%f,%f,%f/%f,%f,%f/%f,%f,%f",
_width, _height, _landFraction, _seed.high, _seed.low,
_landColor.r, _landColor.g, _landColor.b,
_seaColor.r, _seaColor.g, _seaColor.b,
_polarLandColor.r, _polarLandColor.g, _polarLandColor.b,
_polarSeaColor.r, _polarSeaColor.g, _polarSeaColor.b];
}
- (BOOL)getResult:(void **)outData
format:(OOTextureDataFormat *)outFormat
width:(uint32_t *)outWidth
height:(uint32_t *)outHeight
{
BOOL waiting = NO;
if (![self isReady])
{
waiting = true;
OOLog(@"planetTex.temp", @"%s cloud generator %@", "Waiting for", self);
}
BOOL result = [super getResult:outData format:outFormat width:outWidth height:outHeight];
if (waiting)
{
OOLog(@"planetTex.temp", @"%s generator %@", result ? "Dequeued" : "Failed to dequeue", self);
}
else
{
OOLog(@"planetTex.temp", @"%s generator %@ without waiting.", result ? "Dequeued" : "Failed to dequeue", self);
}
return result;
}
- (void) loadTexture
{
OOLog(@"planetTex.temp", @"Started generator %@", self);
BOOL success = NO;
uint8_t *buffer = NULL, *px = NULL;
float *accBuffer = NULL;
float *randomBuffer = NULL;
width = _width;
height = _height;
buffer = malloc(4 * width * height);
if (buffer == NULL) goto END;
px = buffer;
accBuffer = calloc(sizeof (float), width * height);
if (accBuffer == NULL) goto END;
randomBuffer = calloc(sizeof (float), kNoiseBufferSize * kNoiseBufferSize);
if (randomBuffer == NULL) goto END;
FillNoiseBuffer(randomBuffer, _seed);
// Generate basic Perlin noise.
unsigned octave = 8 * PLANET_ASPECT_RATIO;
float scale = 0.5f;
while (octave < height)
{
AddNoise(accBuffer, width, height, octave, scale, randomBuffer);
octave *= 2;
scale *= 0.5;
}
float seaBias = 1.0 - _landFraction;
float poleValue =(_landFraction * accBuffer[0] < seaBias) ? 0.0f : 1.0f;
float q;
unsigned x, y;
FloatRGBA color = (FloatRGBA){_seaColor.r, _seaColor.g, _seaColor.b, 1.0f};
GLfloat shade = 1.0f;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
q = QFactor(accBuffer, x, y, width, height, poleValue, 0.0f);
if (NO) color = CloudMix(q, 0.5, _seaColor, _overallAlpha); // TODO: better values.
*px++ = 255 * color.r * shade;
*px++ = 255 * color.g * shade;
*px++ = 255 * color.b * shade;
*px++ = 255 * q * _overallAlpha;
//*px++ = 255 * color.a;
}
}
success = YES;
format = kOOTextureDataRGBA;
END:
free(accBuffer);
free(randomBuffer);
if (success) data = buffer;
else free(buffer);
OOLog(@"planetTex.temp", @"Completed generator %@ %@successfully", self, success ? @"" : @"un");
#if DEBUG_DUMP
if (success)
{
NSString *name = [NSString stringWithFormat:@"atmosphere-%u-%u-new", _seed.high, _seed.low];
[[UNIVERSE gameView] dumpRGBAToFileNamed:name
bytes:buffer
width:width
height:height
rowBytes:width * 4];
}
#endif
}
@end
static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b)
{
float prime = 1.0f - fraction;
return (FloatRGB)
{
fraction * a.r + prime * b.r,
fraction * a.g + prime * b.g,
fraction * a.b + prime * b.b,
};
}
static FloatRGBA CloudMix(float q, float maxQ, FloatRGB cloudColor, float alpha)
{
#define RECIP_CLOUD_PORTION (20.0f)
#define CLOUD_PORTION (1.0f / RECIP_CLOUD_PORTION)
const FloatRGB white = { 1.0f, 1.0f, 1.0f };
//const FloatRGB black = { 0.0f, 0.0f, 0.0f };
FloatRGB result = cloudColor;
q -= CLOUD_PORTION;
if (q <= 0.0f)
{
if (q >= -CLOUD_PORTION){
alpha *= -q * RECIP_CLOUD_PORTION;
result = Blend( -q * 0.5 * RECIP_CLOUD_PORTION + 0.5, result, white);
}
//else result=black;
}
else if (q >= CLOUD_PORTION)
{
result = Blend( q * 0.5 +0.5, white, result);
}
else if (q < CLOUD_PORTION)
{
alpha *= q * RECIP_CLOUD_PORTION;
result = Blend( q * RECIP_CLOUD_PORTION , result, white);
}
return (FloatRGBA){ result.r, result.g, result.b, alpha * (q )};
}
static FloatRGB FloatRGBFromDictColor(NSDictionary *dictionary, NSString *key)
{
OOColor *color = [dictionary objectForKey:key];
NSCAssert1([color isKindOfClass:[OOColor class]], @"Expected OOColor, got %@", [color class]);
return (FloatRGB){ [color redComponent], [color greenComponent], [color blueComponent] };
}
static void FillNoiseBuffer(float *noiseBuffer, RANROTSeed seed)
{
NSCParameterAssert(noiseBuffer != NULL);
unsigned i;
for (i = 0; i < kNoiseBufferSize * kNoiseBufferSize; i++)
{
noiseBuffer[i] = randfWithSeed(&seed);
}
}
static float lerp(float v0, float v1, float q)
{
return v0 + q * (v1 - v0);
}
static void AddNoise(float *buffer, unsigned width, unsigned height, unsigned octave, float scale, const float *noiseBuffer)
{
unsigned x, y;
float r = (float)width / (float)octave;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
// FIXME: do this with less float/int conversions.
int ix = floor( (float)x / r);
int jx = (ix + 1) % octave;
int iy = floor( (float)y / r);
int jy = (iy + 1) % octave;
float qx = x / r - ix;
float qy = y / r - iy;
ix &= 127;
iy &= 127;
jx &= 127;
jy &= 127;
float rix = lerp( noiseBuffer[iy * kNoiseBufferSize + ix], noiseBuffer[iy * kNoiseBufferSize + jx], qx);
float rjx = lerp( noiseBuffer[jy * kNoiseBufferSize + ix], noiseBuffer[jy * kNoiseBufferSize + jx], qx);
float rfinal = scale * lerp(rix, rjx, qy);
buffer[y * width + x] += rfinal;
}
}
}
static float QFactor(float *accbuffer, int x, int y, unsigned width, unsigned height, float polar_y_value, float bias)
{
x = (x + width) % width;
// FIXME: wrong wrapping mode for Y, should flip to other hemisphere.
y = (y + height) % height;
float q = accbuffer[y * width + x]; // 0.0 -> 1.0
q += bias;
// Polar Y smooth. FIXME: float/int conversions.
float polar_y = (2.0f * y - height) / (float) height;
polar_y *= polar_y;
q = q * (1.0 - polar_y) + polar_y * polar_y_value;
return q;
}

View File

@ -28,7 +28,7 @@ MA 02110-1301, USA.
#import "OOTextureGenerator.h"
#import "OOMaths.h"
@class OOPlanetNormalMapGenerator;
@class OOPlanetNormalMapGenerator, OOPlanetAtmosphereGenerator;
@interface OOPlanetTextureGenerator: OOTextureGenerator
@ -39,14 +39,25 @@ MA 02110-1301, USA.
FloatRGB _seaColor;
FloatRGB _polarLandColor;
FloatRGB _polarSeaColor;
float _cloudAlpha;
float _cloudFraction;
FloatRGB _airColor;
FloatRGB _cloudColor;
FloatRGB _polarAirColor;
FloatRGB _polarCloudColor;
RANROTSeed _seed;
OOPlanetNormalMapGenerator *_nMapGenerator;
OOPlanetAtmosphereGenerator *_atmoGenerator;
OOUInteger _planetScale;
}
- (id) initWithPlanetInfo:(NSDictionary *)planetInfo;
+ (OOTexture *) planetTextureWithInfo:(NSDictionary *)planetInfo;
+ (BOOL) generatePlanetTexture:(OOTexture **)texture andAtmosphere:(OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo;
+ (BOOL) generatePlanetTexture:(OOTexture **)texture secondaryTexture:(OOTexture **)secondaryTexture withInfo:(NSDictionary *)planetInfo;
+ (BOOL) generatePlanetTexture:(OOTexture **)texture secondaryTexture:(OOTexture **)secondaryTexture andAtmosphere:(OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo;
@end

View File

@ -58,6 +58,7 @@ enum
- (NSString *) cacheKeyForType:(NSString *)type;
- (OOTextureGenerator *) normalMapGenerator; // Must be called before generator is enqueued for rendering.
- (OOTextureGenerator *) atmosphereGenerator; // Must be called before generator is enqueued for rendering.
#if DEBUG_DUMP_RAW
- (void) dumpNoiseBuffer:(float *)noise;
@ -66,7 +67,6 @@ enum
@end
/* The planet generator actually generates two textures when shaders are
active, but the texture loader interface assumes we only load/generate
one texture per loader. Rather than complicate that, we use a mock
@ -86,6 +86,21 @@ enum
@end
/* Doing the same as above for the atmosphere. */
@interface OOPlanetAtmosphereGenerator: OOTextureGenerator
{
@private
NSString *_cacheKey;
RANROTSeed _seed;
}
- (id) initWithCacheKey:(NSString *)cacheKey seed:(RANROTSeed)seed;
- (void) completeWithData:(void *)data width:(unsigned)width height:(unsigned)height;
@end
static int heightMask, widthMask;
static float mix_hi, mix_oh, mix_ih, mix_polarCap;
@ -98,7 +113,9 @@ static float QFactor(float *accbuffer, int x, int y, unsigned width, float polar
static float GetQ(float *qbuffer, int x, int y, unsigned width, unsigned height);
static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b);
static float fBlend(float fraction, float a, float b);
static void SetMixConstants(float maxQ, float temperatureFraction);
static FloatRGBA CloudMix(float q, FloatRGB airColor, FloatRGB cloudColor, FloatRGB paleAirColor, FloatRGB paleCloudColor, float alpha, float nearPole);
static FloatRGBA PlanetMix(float q, FloatRGB landColor, FloatRGB seaColor, FloatRGB paleLandColor, FloatRGB paleSeaColor, FloatRGB polarSeaColor, float nearPole);
@ -131,6 +148,17 @@ enum
_polarSeaColor = FloatRGBFromDictColor(planetInfo, @"polar_sea_color");
[[planetInfo objectForKey:@"noise_map_seed"] getValue:&_seed];
if ([planetInfo objectForKey:@"cloud_alpha"])
{
// we have an atmosphere:
_cloudAlpha = [planetInfo oo_floatForKey:@"cloud_alpha" defaultValue:1.0f];
_cloudFraction = OOClamp_0_1_f([planetInfo oo_floatForKey:@"cloud_fraction" defaultValue:0.3]);
_airColor = FloatRGBFromDictColor(planetInfo, @"air_color");
_cloudColor = FloatRGBFromDictColor(planetInfo, @"cloud_color");
_polarAirColor = FloatRGBFromDictColor(planetInfo, @"polar_air_color");
_polarCloudColor = FloatRGBFromDictColor(planetInfo, @"polar_cloud_color");
}
#ifndef TEXGEN_TEST_RIG
if ([UNIVERSE reducedDetail])
{
@ -163,6 +191,25 @@ enum
}
+ (BOOL) generatePlanetTexture:(OOTexture **)texture andAtmosphere:(OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo
{
NSParameterAssert(texture != NULL);
OOPlanetTextureGenerator *diffuseGen = [[[self alloc] initWithPlanetInfo:planetInfo] autorelease];
if (diffuseGen == nil) return NO;
OOTextureGenerator *atmoGen = [diffuseGen atmosphereGenerator];
if (atmoGen == nil) return NO;
*atmosphere = [OOTexture textureWithGenerator:atmoGen];
if (*atmosphere == nil) return NO;
*texture = [OOTexture textureWithGenerator:diffuseGen];
return *texture != nil;
}
+ (BOOL) generatePlanetTexture:(OOTexture **)texture secondaryTexture:(OOTexture **)secondaryTexture withInfo:(NSDictionary *)planetInfo
{
NSParameterAssert(texture != NULL);
@ -185,9 +232,42 @@ enum
}
+ (BOOL) generatePlanetTexture:(OOTexture **)texture secondaryTexture:(OOTexture **)secondaryTexture andAtmosphere:(OOTexture **)atmosphere withInfo:(NSDictionary *)planetInfo
{
NSParameterAssert(texture != NULL);
OOPlanetTextureGenerator *diffuseGen = [[[self alloc] initWithPlanetInfo:planetInfo] autorelease];
if (diffuseGen == nil) return NO;
if (secondaryTexture != NULL)
{
OOTextureGenerator *normalGen = [diffuseGen normalMapGenerator];
if (normalGen == nil) return NO;
*secondaryTexture = [OOTexture textureWithGenerator:normalGen];
if (*secondaryTexture == nil) return NO;
}
OOTextureGenerator *atmoGen = [diffuseGen atmosphereGenerator];
if (atmoGen == nil) return NO;
*atmosphere = [OOTexture textureWithGenerator:atmoGen];
if (*atmosphere == nil)
{
*secondaryTexture = nil;
return NO;
}
*texture = [OOTexture textureWithGenerator:diffuseGen];
return *texture != nil;
}
- (void) dealloc
{
DESTROY(_nMapGenerator);
DESTROY(_atmoGenerator);
[super dealloc];
}
@ -207,7 +287,9 @@ enum
- (NSString *) cacheKey
{
return [self cacheKeyForType:(_nMapGenerator == nil) ? @"diffuse-baked" : @"diffuse-raw"];
NSString *type =(_nMapGenerator == nil) ? @"diffuse-baked" : @"diffuse-raw";
if (_atmoGenerator != nil) type = [NSString stringWithFormat:@"%@-atmo", type];
return [self cacheKeyForType:type];
}
@ -233,6 +315,16 @@ enum
}
- (OOTextureGenerator *) atmosphereGenerator
{
if (_atmoGenerator == nil)
{
_atmoGenerator = [[OOPlanetAtmosphereGenerator alloc] initWithCacheKey:[self cacheKeyForType:@"atmo"] seed:_seed];
}
return _atmoGenerator;
}
- (BOOL)getResult:(void **)outData
format:(OOTextureDataFormat *)outFormat
width:(uint32_t *)outWidth
@ -266,9 +358,11 @@ enum
BOOL success = NO;
BOOL generateNormalMap = (_nMapGenerator != nil);
BOOL generateAtmosphere = (_atmoGenerator != nil);
uint8_t *buffer = NULL, *px = NULL;
uint8_t *nBuffer = NULL, *npx = NULL;
uint8_t *aBuffer = NULL, *apx = NULL;
float *accBuffer = NULL;
float *qBuffer = NULL;
float *randomBuffer = NULL;
@ -289,6 +383,13 @@ enum
npx = nBuffer;
}
if (generateAtmosphere)
{
aBuffer = malloc(4 * width * height);
if (aBuffer == NULL) goto END;
apx = aBuffer;
}
accBuffer = calloc(sizeof (float), width * height);
if (accBuffer == NULL) goto END;
@ -319,17 +420,15 @@ enum
[self dumpNoiseBuffer:accBuffer];
#endif
float polarClouds =(_cloudFraction * accBuffer[0] < 1.0f - _cloudFraction) ? 0.0f : 1.0f;
float poleValue = (_landFraction > 0.5f) ? 0.5f * _landFraction : 0.0f;
float seaBias = _landFraction - 1.0;
float seaBias = _landFraction - 1.0f;
/* The system key 'polar_sea_colour' is used here as 'paleSeaColour'.
While most polar seas would be covoered in ice, and therefore white,
paleSeaColour doesn't seem to take latitutde into account, resulting
in all coastal areas to be white, or whatever defined as polar sea
colours.
For now, I'm overriding paleSeaColour to be pale blend of sea and land,
and widened the shallows.
TODO: investigate the use of polar land colour for the sea at higher latitudes.
/* The system key 'polar_sea_colour' was used as 'paleSeaColour'.
The generated texture had presumably iceberg covered shallows.
paleSeaColour is now a pale blend of sea and land colours, giving
a softer transition colour for the shallows - those have also been
widened from 1.73 to smooth out the coast / deep sea boundary.
-- Kaks
*/
@ -339,17 +438,19 @@ enum
unsigned x, y;
FloatRGBA color;
FloatRGBA cloudColor = (FloatRGBA){_cloudColor.r, _cloudColor.g, _cloudColor.b, 1.0f};
Vector norm;
float q, yN, yS, yW, yE, nearPole;
GLfloat shade;
float rHeight = 1.0f / height;
float fy, fHeight = height;
// The second parameter is the temperature fraction. Most favourable: 1.0f, little ice. Most unfavourable: 0.0f, frozen planet. TODO: make it dependent on ranrot / planetinfo key...
SetMixConstants(_landFraction, 0.95f); // no need to recalculate them inside each loop!
// first pass, calculate q.
for (y = 0; y < height; y++)
for (y = 0, fy = 0.0f; y < height; y++, fy++)
{
nearPole = ((float)(y << 1) - height) * rHeight;
nearPole = (2.0f * fy - fHeight) * rHeight;
nearPole *= nearPole;
for (x = 0; x < width; x++)
@ -359,15 +460,15 @@ enum
}
// second pass, use q.
for (y = 0; y < height; y++)
for (y = 0, fy = 0.0f; y < height; y++, fy++)
{
nearPole = ((float)(y << 1) - height) * rHeight;
nearPole = (2.0f * fy - fHeight) * rHeight;
nearPole *= nearPole;
for (x = 0; x < width; x++)
{
q = qBuffer[y * width + x]; // no need to use GetQ, here x and y will never be out of bounds.
yN = GetQ(qBuffer, x, y - 1, width, height);
q = qBuffer[y * width + x]; // no need to use GetQ, x and y are always within bounds.
yN = GetQ(qBuffer, x, y - 1, width, height); // recalculates x & y if they go out of bounds.
yS = GetQ(qBuffer, x, y + 1, width, height);
yW = GetQ(qBuffer, x - 1, y, width, height);
yE = GetQ(qBuffer, x + 1, y, width, height);
@ -407,7 +508,7 @@ enum
so we can recycle that to avoid branching.
-- Ahruman
*/
shade += color.a - color.a * shade; // equivalent to, but slightly faster than previous calculation
shade += color.a - color.a * shade; // equivalent to - but slightly faster than - previous implementation.
}
*px++ = 255.0f * color.r * shade;
@ -415,6 +516,19 @@ enum
*px++ = 255.0f * color.b * shade;
*px++ = 0; // FIXME: light map goes here.
if (generateAtmosphere)
{
//q = QFactor(accBuffer, x, y, width, polarClouds, _cloudFraction, nearPole);
q=accBuffer[y * width + x];
q *= q;
//color = CloudMix(q, _airColor, _cloudColor, _polarAirColor, _polarCloudColor, _cloudAlpha, nearPole);
color = cloudColor;
*apx++ = 255.0f * color.r;
*apx++ = 255.0f * color.g;
*apx++ = 255.0f * color.b;
*apx++ = 255.0f * _cloudAlpha * q;
}
}
}
@ -428,14 +542,17 @@ END:
if (success)
{
data = buffer;
[_nMapGenerator completeWithData:nBuffer width:width height:height];
if (generateNormalMap) [_nMapGenerator completeWithData:nBuffer width:width height:height];
if (generateAtmosphere) [_atmoGenerator completeWithData:aBuffer width:width height:height];
}
else
{
free(buffer);
free(nBuffer);
free(aBuffer);
}
DESTROY(_nMapGenerator);
DESTROY(_atmoGenerator);
OOLog(@"planetTex.temp", @"Completed generator %@ %@successfully", self, success ? @"" : @"un");
@ -485,6 +602,12 @@ END:
@end
static float fBlend(float fraction, float a, float b)
{
return fraction * a + (1.0f - fraction) * b;
}
static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b)
{
float prime = 1.0f - fraction;
@ -498,6 +621,83 @@ static FloatRGB Blend(float fraction, FloatRGB a, FloatRGB b)
}
static FloatRGBA CloudMix(float q, FloatRGB airColor, FloatRGB cloudColor, FloatRGB paleAirColor, FloatRGB paleCloudColor, float alpha, float nearPole)
{
#define AIR_ALPHA (0.05f)
#define CLOUD_ALPHA (0.50f)
#define POLAR_AIR_ALPHA (0.34f)
#define POLAR_CLOUD_ALPHA (0.75f)
#define POLAR_BOUNDARY (0.66f)
#define RECIP_CLOUD_BOUNDARY (200.0f)
#define CLOUD_BOUNDARY (1.0f / RECIP_CLOUD_BOUNDARY)
FloatRGB result = cloudColor;
float portion = 0.0f;
q -= CLOUD_BOUNDARY;
if (nearPole > POLAR_BOUNDARY)
{
portion = nearPole > POLAR_BOUNDARY + 0.06f ? 1.0f : 0.4f + (nearPole - POLAR_BOUNDARY) * 10.0f; // x * 10 == ((x / 0.06) * 0.6
if (q <= 0.0f)
{
alpha *= fBlend(portion, CLOUD_ALPHA, POLAR_CLOUD_ALPHA);
if (q >= -CLOUD_BOUNDARY)
{
portion = -q * 0.5f * RECIP_CLOUD_BOUNDARY + 0.5f;
result = Blend(portion, paleCloudColor, paleAirColor);
}
else
{
result = paleCloudColor;
}
}
else
{
alpha *= portion * POLAR_AIR_ALPHA;
if (q < CLOUD_BOUNDARY)
{
result = Blend(q * RECIP_CLOUD_BOUNDARY, paleAirColor, paleCloudColor);
}
else
{
result = paleAirColor;
}
}
}
else
{
if (q <= 0.0f)
{
if (q >= -CLOUD_BOUNDARY){
portion = -q * 0.5f * RECIP_CLOUD_BOUNDARY + 0.5f;
alpha *= portion * CLOUD_ALPHA;
result = Blend(portion, cloudColor, airColor);
}
else
{
result = cloudColor;
alpha *= CLOUD_ALPHA;
}
}
else if (q < CLOUD_BOUNDARY)
{
alpha *= AIR_ALPHA;
result = Blend(q * RECIP_CLOUD_BOUNDARY, airColor, cloudColor);
}
else if (q >= CLOUD_BOUNDARY)
{
alpha *= AIR_ALPHA;
result = airColor;
}
}
return (FloatRGBA){ result.r, result.g, result.b, alpha};
}
static FloatRGBA PlanetMix(float q, FloatRGB landColor, FloatRGB seaColor, FloatRGB paleLandColor, FloatRGB paleSeaColor, FloatRGB polarSeaColor, float nearPole)
{
float phi = mix_polarCap + mix_polarCap - nearPole; // (q > mix_polarCap + mix_polarCap - nearPole) == ((nearPole + q) / 2 > mix_polarCap)
@ -632,34 +832,38 @@ OOINLINE float Hermite(float q)
static void AddNoise(float *buffer, unsigned width, unsigned height, float octave, unsigned octaveMask, float scale, const float *noiseBuffer)
{
unsigned x, y;
int ix, jx, iy, jy;
float rr = octave / width;
float *dst = buffer;
float fx, fy;
float fx, fy, qx, qy, rix, rjx, rfinal;
for (fy = 0, y = 0; y < height; fy++, y++)
{
// FIXME: do this with less float/int conversions.
iy = fy * rr; // FLOAT->INT
jy = (iy + 1) & octaveMask;
qy = fy * rr - iy;
iy &= (kNoiseBufferSize - 1);
jy &= (kNoiseBufferSize - 1);
#if HERMITE
qy = Hermite(qy);
#endif
for (fx = 0, x = 0; x < width; fx++, x++)
{
// FIXME: do this with less float/int conversions.
int ix = fx * rr; // FLOAT->INT
int jx = (ix + 1) & octaveMask;
int iy = fy * rr; // FLOAT->INT
int jy = (iy + 1) & octaveMask;
float qx = fx * rr - ix;
float qy = fy * rr - iy;
ix = fx * rr; // FLOAT->INT
jx = (ix + 1) & octaveMask;
qx = fx * rr - ix;
ix &= (kNoiseBufferSize - 1);
iy &= (kNoiseBufferSize - 1);
jx &= (kNoiseBufferSize - 1);
jy &= (kNoiseBufferSize - 1);
#if HERMITE
qx = Hermite(qx);
qy = Hermite(qy);
#endif
float rix = Lerp(noiseBuffer[iy * kNoiseBufferSize + ix], noiseBuffer[iy * kNoiseBufferSize + jx], qx);
float rjx = Lerp(noiseBuffer[jy * kNoiseBufferSize + ix], noiseBuffer[jy * kNoiseBufferSize + jx], qx);
float rfinal = scale * Lerp(rix, rjx, qy);
rix = Lerp(noiseBuffer[iy * kNoiseBufferSize + ix], noiseBuffer[iy * kNoiseBufferSize + jx], qx);
rjx = Lerp(noiseBuffer[jy * kNoiseBufferSize + ix], noiseBuffer[jy * kNoiseBufferSize + jx], qx);
rfinal = scale * Lerp(rix, rjx, qy);
*dst++ += rfinal;
}
@ -777,3 +981,72 @@ static void SetMixConstants(float maxQ, float temperatureFraction)
}
@end
@implementation OOPlanetAtmosphereGenerator
- (id) initWithCacheKey:(NSString *)cacheKey seed:(RANROTSeed)seed
{
if ((self = [super init]))
{
_cacheKey = [cacheKey copy];
_seed = seed;
}
return self;
}
- (void) dealloc
{
DESTROY(_cacheKey);
[super dealloc];
}
- (NSString *) cacheKey
{
return _cacheKey;
}
- (uint32_t) textureOptions
{
return PLANET_TEXTURE_OPTIONS;
}
- (BOOL) enqueue
{
return YES;
}
- (void) loadTexture
{
// Do nothing.
}
- (void) completeWithData:(void *)data_ width:(unsigned)width_ height:(unsigned)height_
{
data = data_;
width = width_;
height = height_;
format = kOOTextureDataRGBA;
// Enqueue so superclass can apply texture options and so forth.
[super enqueue];
#if DEBUG_DUMP
NSString *name = [NSString stringWithFormat:@"planet-%u-%u-atmosphere-new", _seed.high, _seed.low];
[[UNIVERSE gameView] dumpRGBAToFileNamed:name
bytes:data
width:width
height:height
rowBytes:width * 4];
#endif
}
@end

View File

@ -506,6 +506,7 @@ enum
- (void) setSystemDataForGalaxy:(OOGalaxyID) gnum planet:(OOSystemID) pnum key:(NSString *)key value:(id)object;
- (id) getSystemDataForGalaxy:(OOGalaxyID) gnum planet:(OOSystemID) pnum key:(NSString *)key;
- (NSString *) getSystemName:(Random_Seed) s_seed;
- (OOGovernmentID) getSystemGovernment:(Random_Seed)s_seed;
- (NSString *) getSystemInhabitants:(Random_Seed) s_seed;
- (NSString *) getSystemInhabitants:(Random_Seed) s_seed plural:(BOOL)plural;
- (NSString *) generateSystemName:(Random_Seed) system_seed;
@ -544,8 +545,8 @@ double estimatedTimeForJourney(double distance, int hops);
- (NSString *) shortTimeDescription:(OOTimeDelta) interval;
- (Random_Seed) marketSeed;
- (NSArray *) passengersForSystem:(Random_Seed) s_seed atTime:(OOTimeAbsolute) current_time;
- (NSArray *) contractsForSystem:(Random_Seed) s_seed atTime:(OOTimeAbsolute) current_time;
- (NSArray *) passengersForLocalSystemAtTime:(OOTimeAbsolute) current_time;
- (NSArray *) contractsForLocalSystemAtTime:(OOTimeAbsolute) current_time;
- (NSArray *) shipsForSaleForSystem:(Random_Seed) s_seed withTL:(OOTechLevelID) specialTL atTime:(OOTimeAbsolute) current_time;
/* Calculate base cost, before depreciation */

View File

@ -469,7 +469,7 @@ OOINLINE size_t class_getInstanceSize(Class cls)
[self initPlayerSettings];
autoSaveNow = NO; // don't autosave immediately after loading / restarting game!
[[self station] initialiseLocalMarketWithSeed:system_seed andRandomFactor:[player random_factor]];
[[self station] initialiseLocalMarketWithRandomFactor:[player random_factor]];
if(showDemo)
{
@ -6274,7 +6274,7 @@ static NSDictionary *sCachedSystemData = nil;
{
if ([key isEqualToString:KEY_ECONOMY])
{
if([self station]) [[self station] initialiseLocalMarketWithSeed:s_seed andRandomFactor:[[PlayerEntity sharedPlayer] random_factor]];
if([self station]) [[self station] initialiseLocalMarketWithRandomFactor:[[PlayerEntity sharedPlayer] random_factor]];
}
else if ([key isEqualToString:KEY_TECHLEVEL])
{
@ -6357,6 +6357,12 @@ static NSDictionary *sCachedSystemData = nil;
return [[self generateSystemData:s_seed] oo_stringForKey:KEY_NAME];
}
- (OOGovernmentID) getSystemGovernment:(Random_Seed)s_seed
{
return [[self generateSystemData:s_seed] oo_unsignedCharForKey:KEY_GOVERNMENT];
}
- (NSString *) getSystemInhabitants:(Random_Seed) s_seed
{
@ -6968,13 +6974,13 @@ double estimatedTimeForJourney(double distance, int hops)
}
- (NSArray *) passengersForSystem:(Random_Seed) s_seed atTime:(OOTimeAbsolute) current_time
- (NSArray *) passengersForLocalSystemAtTime:(OOTimeAbsolute) current_time
{
PlayerEntity* player = [PlayerEntity sharedPlayer];
int player_repute = [player passengerReputation];
int start = [self findSystemNumberAtCoords:NSMakePoint(s_seed.d, s_seed.b) withGalaxySeed:galaxy_seed];
NSString* native_species = [self getSystemInhabitants:s_seed plural:NO];
int start = [self currentSystemID];
NSString* native_species = [self getSystemInhabitants:system_seed plural:NO];
// passenger seed is calculated in a similar way to all other market seeds
// but gives better results when done .a to .f instead of .f to .a...
@ -6984,7 +6990,7 @@ double estimatedTimeForJourney(double distance, int hops)
long random_factor = current_time;
random_factor = (random_factor >> 24) &0xff;
Random_Seed passenger_seed = s_seed;
Random_Seed passenger_seed = system_seed;
passenger_seed.a ^= random_factor; // XOR
passenger_seed.b ^= passenger_seed.a; // XOR
passenger_seed.c ^= passenger_seed.b; // XOR
@ -6995,13 +7001,13 @@ double estimatedTimeForJourney(double distance, int hops)
// 'standardised' passenger seed - not as good as the traditional one.
//Random_Seed passenger_seed = [self marketSeed];
NSMutableArray* resultArray = [NSMutableArray arrayWithCapacity:255];
NSMutableArray* resultArray = [NSMutableArray arrayWithCapacity:256];
unsigned i = 0;
long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
for (i = 0; i < 256; i++)
{
long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
long long passenger_time = passenger_seed.a * 0x10000 + passenger_seed.b * 0x100 + passenger_seed.c;
double passenger_departure_time = reference_time + passenger_time;
@ -7022,22 +7028,23 @@ double estimatedTimeForJourney(double distance, int hops)
BOOL lowercaseIgnore = [[self descriptions] oo_boolForKey:@"lowercase_ignore"]; // i18n.
// determine the passenger's species
int passenger_species = passenger_seed.f & 3; // 0-1 native, 2 human colonial, 3 other
NSString* passenger_species_string = [NSString stringWithString:native_species];
if (passenger_species == 2)
passenger_species_string = DESC(@"human-colonial-description%0");
if (passenger_species == 3)
NSString* passenger_species_string = nil;
switch (passenger_species)
{
passenger_species_string = [self getSystemInhabitants:passenger_seed plural:NO];
}
if(!lowercaseIgnore)
{
passenger_species_string = [[passenger_species_string lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
else
{
passenger_species_string = [passenger_species_string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
case 2:
passenger_species_string = DESC(@"human-colonial-description%0");
break;
case 3:
passenger_species_string = [self getSystemInhabitants:passenger_seed plural:NO];
break;
default:
passenger_species_string = [NSString stringWithString:native_species];
break;
}
if (!lowercaseIgnore) passenger_species_string = [passenger_species_string lowercaseString];
passenger_species_string = [passenger_species_string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// determine the passenger's name
seed_RNG_only_for_planet_description(passenger_seed);
NSString* passenger_name = [NSString stringWithFormat:@"%@ %@", ExpandDescriptionForSeed(@"%R", passenger_seed), ExpandDescriptionForSeed(@"%R", passenger_seed)];
@ -7183,7 +7190,7 @@ double estimatedTimeForJourney(double distance, int hops)
}
- (NSArray *) contractsForSystem:(Random_Seed) s_seed atTime:(double) current_time
- (NSArray *) contractsForLocalSystemAtTime:(double) current_time
{
PlayerEntity* player = [PlayerEntity sharedPlayer];
@ -7194,21 +7201,21 @@ double estimatedTimeForJourney(double distance, int hops)
random_factor = (random_factor >> 24) &0xff;
Random_Seed contract_seed = [self marketSeed];
int start = [self findSystemNumberAtCoords:NSMakePoint(s_seed.d, s_seed.b) withGalaxySeed:galaxy_seed];
int start = [self currentSystemID];
NSMutableArray* resultArray = [NSMutableArray arrayWithCapacity:255];
NSMutableArray* resultArray = [NSMutableArray arrayWithCapacity:256];
int i = 0;
NSArray* localMarket;
if ([[self station] localMarket])
localMarket = [[self station] localMarket];
else
localMarket = [[self station] initialiseLocalMarketWithSeed:s_seed andRandomFactor:random_factor];
localMarket = [[self station] initialiseLocalMarketWithRandomFactor:random_factor];
long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
for (i = 0; i < 256; i++)
{
long long reference_time = 0x1000000 * floor(current_time / 0x1000000);
long long contract_time = contract_seed.a * 0x10000 + contract_seed.b * 0x100 + contract_seed.c;
double contract_departure_time = reference_time + contract_time;