LCOV - code coverage report
Current view: top level - Core/Materials - OOCombinedEmissionMapGenerator.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 16 0.0 %
Date: 2025-06-23 16:19:27 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOCombinedEmissionMapGenerator.m
       4             : 
       5             : 
       6             : Copyright (C) 2010-2013 Jens Ayton
       7             : 
       8             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9             : of this software and associated documentation files (the "Software"), to deal
      10             : in the Software without restriction, including without limitation the rights
      11             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             : copies of the Software, and to permit persons to whom the Software is
      13             : furnished to do so, subject to the following conditions:
      14             : 
      15             : The above copyright notice and this permission notice shall be included in all
      16             : copies or substantial portions of the Software.
      17             : 
      18             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             : SOFTWARE.
      25             : 
      26             : */
      27             : 
      28             : #import "OOCombinedEmissionMapGenerator.h"
      29             : 
      30             : #import "OOColor.h"
      31             : #import "OOPixMapChannelOperations.h"
      32             : #import "OOTextureScaling.h"
      33             : #import "OOTextureInternal.h"
      34             : #import "OOMaterialSpecifier.h"
      35             : #import "OOCollectionExtractors.h"
      36             : 
      37             : 
      38           0 : #define DUMP_COMBINER   0
      39             : 
      40             : 
      41             : static OOColor *ModulateColor(OOColor *a, OOColor *b);
      42             : static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB);
      43             : 
      44             : 
      45             : @interface OOCombinedEmissionMapGenerator (Private)
      46             : 
      47           0 : - (id) initWithEmissionMapSpec:(NSDictionary *)emissionMapSpec
      48             :                                  emissionColor:(OOColor *)emissionColor
      49             :                                         diffuseMap:(OOTexture *)diffuseMap
      50             :                                   diffuseColor:(OOColor *)diffuseColor
      51             :                    illuminationMapSpec:(NSDictionary *)illuminationMapSpec
      52             :                          illuminationColor:(OOColor *)illuminationColor
      53             :                                  isCombinedMap:(BOOL)isCombinedMap
      54             :                           optionsSpecifier:(NSDictionary *)spec;
      55             : 
      56           0 : - (NSString *)constructCacheKey;
      57             : 
      58             : @end
      59             : 
      60             : 
      61             : @implementation OOCombinedEmissionMapGenerator
      62             : 
      63             : - (id) initWithEmissionMapSpec:(NSDictionary *)emissionMapSpec
      64             :                                  emissionColor:(OOColor *)emissionColor
      65             :                                         diffuseMap:(OOTexture *)diffuseMap
      66             :                                   diffuseColor:(OOColor *)diffuseColor
      67             :                    illuminationMapSpec:(NSDictionary *)illuminationMapSpec
      68             :                          illuminationColor:(OOColor *)illuminationColor
      69             :                           optionsSpecifier:(NSDictionary *)spec
      70             : {
      71             :         return [self initWithEmissionMapSpec:emissionMapSpec
      72             :                                                    emissionColor:emissionColor
      73             :                                                           diffuseMap:diffuseMap
      74             :                                                         diffuseColor:diffuseColor
      75             :                                          illuminationMapSpec:illuminationMapSpec
      76             :                                            illuminationColor:illuminationColor
      77             :                                                    isCombinedMap:NO
      78             :                                                 optionsSpecifier:spec];
      79             : }
      80             : 
      81             : 
      82             : - (id) initWithEmissionAndIlluminationMapSpec:(NSDictionary *)emissionAndIlluminationMapSpec
      83             :                                                                    diffuseMap:(OOTexture *)diffuseMap
      84             :                                                                  diffuseColor:(OOColor *)diffuseColor
      85             :                                                                 emissionColor:(OOColor *)emissionColor
      86             :                                                         illuminationColor:(OOColor *)illuminationColor
      87             :                                                          optionsSpecifier:(NSDictionary *)spec
      88             : {
      89             :         return [self initWithEmissionMapSpec:emissionAndIlluminationMapSpec
      90             :                                                    emissionColor:emissionColor
      91             :                                                           diffuseMap:diffuseMap
      92             :                                                         diffuseColor:diffuseColor
      93             :                                          illuminationMapSpec:nil
      94             :                                            illuminationColor:illuminationColor
      95             :                                                    isCombinedMap:YES
      96             :                                                 optionsSpecifier:spec];
      97             : }
      98             : 
      99             : 
     100           0 : - (id) initWithEmissionMapSpec:(NSDictionary *)emissionMapSpec
     101             :                                  emissionColor:(OOColor *)emissionColor
     102             :                                         diffuseMap:(OOTexture *)diffuseMap
     103             :                                   diffuseColor:(OOColor *)diffuseColor
     104             :                    illuminationMapSpec:(NSDictionary *)illuminationMapSpec
     105             :                          illuminationColor:(OOColor *)illuminationColor
     106             :                                  isCombinedMap:(BOOL)isCombinedMap
     107             :                           optionsSpecifier:(NSDictionary *)spec
     108             : {
     109             :         if (emissionMapSpec == nil && illuminationMapSpec == nil)
     110             :         {
     111             :                 [self release];
     112             :                 return nil;
     113             :         }
     114             :         
     115             :         NSParameterAssert(illuminationMapSpec == nil || !isCombinedMap);
     116             :         
     117             :         uint32_t options;
     118             :         GLfloat anisotropy;
     119             :         GLfloat lodBias;
     120             :         OOInterpretTextureSpecifier(spec, NULL, &options, &anisotropy, &lodBias, YES);
     121             :         options = OOApplyTextureOptionDefaults(options);
     122             :         
     123             :         if ((self = [super initWithPath:@"<generated emission map>" options:options]))
     124             :         {
     125             :                 /*      Illumination contribution is:
     126             :                         illuminationMap * illuminationColor * diffuseMap * diffuseColor
     127             :                         Since illuminationColor and diffuseColor aren't used otherwise,
     128             :                         we may as well combine them up front.
     129             :                 */
     130             :                 illuminationColor = ModulateColor(diffuseColor, illuminationColor);
     131             :                                                                                   
     132             :                 if ([emissionColor isWhite])  emissionColor = nil;
     133             :                 if ([illuminationColor isWhite])  illuminationColor = nil;
     134             :                 if (!isCombinedMap && illuminationMapSpec == nil)  diffuseMap = nil;    // Diffuse map is only used with illumination
     135             :                 
     136             :                 // Insert extraShrink flag here instead of using extraOptions later because we need it in cache key too.
     137             :                 NSMutableDictionary *emissionSpec = [emissionMapSpec mutableCopy];
     138             :                 [emissionSpec oo_setBool:YES forKey:kOOTextureSpecifierExtraShrinkKey];
     139             :                 _emissionSpec = emissionSpec;
     140             :                 
     141             :                 NSMutableDictionary *illuminationSpec = [illuminationMapSpec mutableCopy];
     142             :                 [illuminationSpec oo_setBool:YES forKey:kOOTextureSpecifierExtraShrinkKey];
     143             :                 _illuminationSpec = illuminationSpec;
     144             :                 
     145             :                 _diffuseMap = [diffuseMap retain];
     146             :                 
     147             :                 _emissionColor = [emissionColor retain];
     148             :                 _illuminationColor = [illuminationColor retain];
     149             :                 _isCombinedMap = isCombinedMap;
     150             :                 
     151             :                 _textureOptions = options;
     152             :                 _anisotropy = anisotropy;
     153             :                 _lodBias = lodBias;
     154             :                 
     155             :                 _cacheKey = [self constructCacheKey];
     156             :                 
     157             :                 if ([OOTexture existingTextureForKey:_cacheKey] == nil)
     158             :                 {
     159             :                         /*      Extract pixmap from diffuse map. This must be done in the main
     160             :                                 thread even if scheduling is fixed, because it might involve
     161             :                                 reading back pixels from OpenGL.
     162             :                         */
     163             :                         if (diffuseMap != nil)
     164             :                         {
     165             :                                 _diffusePx = [diffuseMap copyPixMapRepresentation];
     166             : #ifndef NDEBUG
     167             :                                 _diffuseDesc = [[diffuseMap shortDescription] copy];
     168             : #endif
     169             :                         }
     170             :                         
     171             :                         /*      Extract emission and illumination pixmaps from loaders. Ideally,
     172             :                                 this would be done asynchronously, but that requires dependency
     173             :                                 management in OOAsyncWorkManager.
     174             :                         */
     175             :                         OOTextureDataFormat format;
     176             :                         if (_emissionSpec != nil)
     177             :                         {
     178             :                                 OOTextureLoader *emissionMapLoader = [OOTextureLoader loaderWithTextureSpecifier:_emissionSpec
     179             :                                                                                                                                                                         extraOptions:0
     180             :                                                                                                                                                                                   folder:@"Textures"];
     181             :                                 [emissionMapLoader getResult:&_emissionPx format:&format originalWidth:NULL originalHeight:NULL];
     182             : #ifndef NDEBUG
     183             :                                 _emissionDesc = [[emissionMapLoader shortDescription] copy];
     184             : #endif
     185             :                         }
     186             :                         if (_illuminationSpec != nil)
     187             :                         {
     188             :                                 OOTextureLoader *illuminationMapLoader = [OOTextureLoader loaderWithTextureSpecifier:_illuminationSpec
     189             :                                                                                                                                                                                 extraOptions:0
     190             :                                                                                                                                                                                           folder:@"Textures"];
     191             :                                 [illuminationMapLoader getResult:&_illuminationPx format:&format originalWidth:NULL originalHeight:NULL];
     192             : #ifndef NDEBUG
     193             :                                 _illuminationDesc = [[illuminationMapLoader shortDescription] copy];
     194             : #endif
     195             :                         }
     196             :                 }
     197             :         }
     198             :         
     199             :         return self;
     200             : }
     201             : 
     202             : 
     203           0 : - (NSString *)constructCacheKey
     204             : {
     205             :         NSMutableString *cacheKey = [NSMutableString string];
     206             :         
     207             :         if (_isCombinedMap)  [cacheKey appendString:@"combined emission and illumination map;"];
     208             :         else  if (_emissionSpec == nil)  [cacheKey appendString:@"illumination map;"];
     209             :         else  if (_illuminationSpec == nil)  [cacheKey appendString:@"emission map;"];
     210             :         else [cacheKey appendString:@"merged emission and illumination map;"];
     211             :         
     212             :         NSString *emissionDesc = nil;
     213             :         if (_emissionSpec != nil)
     214             :         {
     215             :                 emissionDesc = OOTextureCacheKeyForSpecifier(_emissionSpec);
     216             :                 [cacheKey appendFormat:@"emission:{%@}", emissionDesc];
     217             :                 if (_emissionColor != nil)  [cacheKey appendFormat:@"*%@", [_emissionColor rgbaDescription]];
     218             :                 [cacheKey appendString:@";"];
     219             :         }
     220             :         
     221             :         NSString *illuminationDesc = nil;
     222             :         if (_isCombinedMap)
     223             :         {
     224             :                 illuminationDesc = [NSString stringWithFormat:@"%@:a", emissionDesc];
     225             :         }
     226             :         else if (_illuminationSpec != nil)
     227             :         {
     228             :                 illuminationDesc = OOTextureCacheKeyForSpecifier(_illuminationSpec);
     229             :         }
     230             :         
     231             :         if (illuminationDesc != nil)
     232             :         {
     233             :                 [cacheKey appendFormat:@"illumination:{%@}*{%@}", illuminationDesc, [_diffuseMap cacheKey]];
     234             :                 if (_illuminationColor != nil)  [cacheKey appendFormat:@"*%@", [_illuminationColor rgbaDescription]];
     235             :                 [cacheKey appendString:@";"];
     236             :         }
     237             :         
     238             :         return cacheKey;
     239             : }
     240             : 
     241             : 
     242           0 : - (void) dealloc
     243             : {
     244             :         DESTROY(_emissionSpec);
     245             :         DESTROY(_illuminationSpec);
     246             :         DESTROY(_diffuseMap);
     247             :         
     248             :         OOFreePixMap(&_emissionPx);
     249             :         OOFreePixMap(&_illuminationPx);
     250             :         OOFreePixMap(&_diffusePx);
     251             :         DESTROY(_emissionColor);
     252             :         DESTROY(_illuminationColor);
     253             :         
     254             : #ifndef NDEBUG
     255             :         DESTROY(_diffuseDesc);
     256             :         DESTROY(_emissionDesc);
     257             :         DESTROY(_illuminationDesc);
     258             : #endif
     259             :         
     260             :         [super dealloc];
     261             : }
     262             : 
     263             : 
     264             : #ifndef NDEBUG
     265           0 : - (NSString *) descriptionComponents
     266             : {
     267             :         NSMutableString *result = [NSMutableString string];
     268             :         BOOL haveIllumination = NO;
     269             :         
     270             :         if (_emissionDesc != nil)
     271             :         {
     272             :                 [result appendFormat:@"emission map: %@", _emissionDesc];
     273             :                 if (_isCombinedMap)
     274             :                 {
     275             :                         [result appendString:@".rgb"];
     276             :                 }
     277             :                 if (_emissionColor != nil)
     278             :                 {
     279             :                         [result appendFormat:@" * %@", [_emissionColor rgbaDescription]];
     280             :                 }
     281             :                 
     282             :                 if (_isCombinedMap)
     283             :                 {
     284             :                         [result appendFormat:@", illumination map: %@.a", _emissionDesc];
     285             :                         haveIllumination = YES;
     286             :                 }
     287             :         }
     288             :         
     289             :         if (_illuminationDesc != nil)
     290             :         {
     291             :                 if (_emissionDesc != nil)  [result appendString:@", "];
     292             :                 [result appendFormat:@"illumination map: %@", _illuminationDesc];
     293             :                 haveIllumination = YES;
     294             :         }
     295             :         
     296             :         if (haveIllumination)
     297             :         {
     298             :                 if (_diffuseDesc != nil)
     299             :                 {
     300             :                         [result appendFormat:@" * %@", _diffuseDesc];
     301             :                 }
     302             :                 if (_illuminationColor != nil)
     303             :                 {
     304             :                         [result appendFormat:@" * %@", [_illuminationColor rgbaDescription]];
     305             :                 }
     306             :         }
     307             :         
     308             :         return result;
     309             : }
     310             : #endif
     311             : 
     312             : 
     313           0 : - (uint32_t) textureOptions
     314             : {
     315             :         return _textureOptions;
     316             : }
     317             : 
     318             : 
     319           0 : - (GLfloat) anisotropy
     320             : {
     321             :         return _anisotropy;
     322             : }
     323             : 
     324             : 
     325           0 : - (GLfloat) lodBias
     326             : {
     327             :         return _lodBias;
     328             : }
     329             : 
     330             : 
     331           0 : - (NSString *) cacheKey
     332             : {
     333             :         return _cacheKey;
     334             : }
     335             : 
     336             : 
     337           0 : - (void) loadTexture
     338             : {
     339             :         OOPixMap illuminationPx = kOONullPixMap;
     340             :         BOOL haveEmission = NO, haveIllumination = NO, haveDiffuse = NO;
     341             :         
     342             : #if DUMP_COMBINER
     343             :         static unsigned sTexID = 0;
     344             :         unsigned texID = ++sTexID, dumpCount = 0;
     345             :         
     346             : #define DUMP(pm, label) OODumpPixMap(pm, [NSString stringWithFormat:@"lightmap %u.%u - %@", texID, ++dumpCount, label]);
     347             : #else
     348           0 : #define DUMP(pm, label) do {} while (0)
     349             : #endif
     350             :         
     351             :         haveEmission = !OOIsNullPixMap(_emissionPx);
     352             :         if (haveEmission)  DUMP(_emissionPx, @"source emission map");
     353             :         
     354             :         // Extract illumination component if emission_and_illumination_map.
     355             :         if (haveEmission && _isCombinedMap && OOPixMapFormatHasAlpha(_emissionPx.format))
     356             :         {
     357             :                 OOPixMapToRGBA(&_emissionPx);
     358             :                 illuminationPx = OODuplicatePixMap(_emissionPx, 0);
     359             :                 OOExtractPixMapChannel(&illuminationPx, 3, YES);
     360             :                 haveIllumination = YES;
     361             :                 DUMP(illuminationPx, @"extracted illumination map");
     362             :         }
     363             :         
     364             :         // Tint emission map if necessary.
     365             :         if (haveEmission && _emissionColor != nil)
     366             :         {
     367             :                 OOPixMapModulateUniform(&_emissionPx, [_emissionColor redComponent], [_emissionColor greenComponent], [_emissionColor blueComponent], 1.0);
     368             :                 DUMP(_emissionPx, @"modulated emission map");
     369             :         }
     370             :         
     371             :         if (!OOIsNullPixMap(_illuminationPx))
     372             :         {
     373             :                 NSAssert(!_isCombinedMap, @"OOCombinedEmissionMapGenerator configured with both illumination map and combined emission/illumination map.");
     374             :                 
     375             :                 illuminationPx = _illuminationPx;
     376             :                 _illuminationPx.pixels = NULL;
     377             :                 haveIllumination = YES;
     378             :                 DUMP(illuminationPx, @"source illumination map");
     379             :         }
     380             :         
     381             :         // Tint illumination map if necessary.
     382             :         if (haveIllumination && _illuminationColor != nil)
     383             :         {
     384             :                 OOPixMapModulateUniform(&illuminationPx, [_illuminationColor redComponent], [_illuminationColor greenComponent], [_illuminationColor blueComponent], 1.0);
     385             :                 DUMP(illuminationPx, @"modulated illumination map");
     386             :         }
     387             :         
     388             :         // Load diffuse map and combine with illumination map.
     389             :         haveDiffuse = !OOIsNullPixMap(_diffusePx);
     390             :         if (haveDiffuse)  DUMP(_diffusePx, @"source diffuse map");
     391             :         
     392             :         if (haveIllumination && haveDiffuse)
     393             :         {
     394             :                 // Modulate illumination with diffuse map.
     395             :                 ScaleToMatch(&_diffusePx, &illuminationPx);
     396             :                 OOPixMapToRGBA(&_diffusePx);
     397             :                 OOPixMapModulatePixMap(&illuminationPx, _diffusePx);
     398             :                 DUMP(illuminationPx, @"combined diffuse and illumination map");
     399             :         }
     400             :         OOFreePixMap(&_diffusePx);
     401             :         
     402             :         if (haveIllumination)
     403             :         {
     404             :                 if (haveEmission)
     405             :                 {
     406             :                         OOPixMapToRGBA(&illuminationPx);
     407             :                         OOPixMapAddPixMap(&_emissionPx, illuminationPx);
     408             :                         OOFreePixMap(&illuminationPx);
     409             :                         DUMP(_emissionPx, @"combined emission and illumination map");
     410             :                 }
     411             :                 else if (haveIllumination)
     412             :                 {
     413             :                         // No explicit emission map -> modulated illumination map is our only emission map.
     414             :                         _emissionPx = illuminationPx;
     415             :                         haveEmission = YES;
     416             :                         illuminationPx.pixels = NULL;
     417             :                 }
     418             :                 haveIllumination = NO;  // Either way, illumination is now baked into emission.
     419             :         }
     420             :         
     421             :         (void)haveEmission;
     422             :         (void)haveIllumination;
     423             :         
     424             :         // Done: emissionPx now contains combined emission map.
     425             :         OOCompactPixMap(&_emissionPx);
     426             :         if (OOIsValidPixMap(_emissionPx))
     427             :         {
     428             :                 _data = _emissionPx.pixels;
     429             :                 _width = _emissionPx.width;
     430             :                 _height = _emissionPx.height;
     431             :                 _rowBytes = _emissionPx.rowBytes;
     432             :                 _format = _emissionPx.format;
     433             :                 
     434             :                 _emissionPx.pixels = NULL;      // So it won't be freed by -dealloc.
     435             :         }
     436             :         if (_data == NULL)
     437             :         {
     438             :                 OOLogERR(@"texture.combinedEmissionMap.error", @"Unknown error loading %@", self);
     439             :         }
     440             : }
     441             : 
     442             : @end
     443             : 
     444             : 
     445           0 : static OOColor *ModulateColor(OOColor *a, OOColor *b)
     446             : {
     447             :         if (a == nil)  return b;
     448             :         if (b == nil)  return a;
     449             :         
     450             :         OORGBAComponents ac, bc;
     451             :         ac = [a rgbaComponents];
     452             :         bc = [b rgbaComponents];
     453             :         
     454             :         ac.r *= bc.r;
     455             :         ac.g *= bc.g;
     456             :         ac.b *= bc.b;
     457             :         ac.a *= bc.a;
     458             :         
     459             :         return [OOColor colorWithRGBAComponents:ac];
     460             : }
     461             : 
     462             : 
     463           0 : static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB)
     464             : {
     465             :         NSCParameterAssert(pmA != NULL && pmB != NULL && OOIsValidPixMap(*pmA) && OOIsValidPixMap(*pmB));
     466             :         
     467             :         OOPixMapDimension minWidth = MIN(pmA->width, pmB->width);
     468             :         OOPixMapDimension minHeight = MIN(pmA->height, pmB->height);
     469             :         
     470             :         if (pmA->width != minWidth || pmA->height != minHeight)
     471             :         {
     472             :                 *pmA = OOScalePixMap(*pmA, minWidth, minHeight, NO);
     473             :         }
     474             :         if (pmB->width != minWidth || pmB->height != minHeight)
     475             :         {
     476             :                 *pmB = OOScalePixMap(*pmB, minWidth, minHeight, NO);
     477             :         }
     478             : }

Generated by: LCOV version 1.14