Line data Source code
1 0 : /*
2 :
3 : OOMultiTextureMaterial.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 "OOMultiTextureMaterial.h"
29 : #import "OOCombinedEmissionMapGenerator.h"
30 : #import "OOOpenGLExtensionManager.h"
31 : #import "OOTexture.h"
32 : #import "OOMacroOpenGL.h"
33 : #import "NSDictionaryOOExtensions.h"
34 : #import "OOMaterialSpecifier.h"
35 :
36 : #if OO_MULTITEXTURE
37 :
38 :
39 : @implementation OOMultiTextureMaterial
40 :
41 : - (id)initWithName:(NSString *)name configuration:(NSDictionary *)configuration
42 : {
43 : if (![[OOOpenGLExtensionManager sharedManager] textureCombinersSupported])
44 : {
45 : [self release];
46 : return nil;
47 : }
48 :
49 : NSDictionary *diffuseSpec = [configuration oo_diffuseMapSpecifierWithDefaultName:name];
50 : NSDictionary *emissionSpec = [configuration oo_emissionMapSpecifier];
51 : NSDictionary *illuminationSpec = [configuration oo_illuminationMapSpecifier];
52 : NSDictionary *emissionAndIlluminationSpec = [configuration oo_emissionAndIlluminationMapSpecifier];
53 : OOColor *diffuseColor = [configuration oo_diffuseColor];
54 : OOColor *emissionColor = nil;
55 : OOColor *illuminationColor = [configuration oo_illuminationModulateColor];
56 :
57 : NSMutableDictionary *mutableConfiguration = [NSMutableDictionary dictionaryWithDictionary:configuration];
58 :
59 : if (emissionSpec != nil || emissionAndIlluminationSpec != nil)
60 : {
61 : emissionColor = [configuration oo_emissionModulateColor];
62 :
63 : /* If an emission map and an emission colour are both specified, stop
64 : the superclass (OOBasicMaterial) from applying the emission colour.
65 : */
66 : [mutableConfiguration removeObjectForKey:kOOMaterialEmissionColorName];
67 : [mutableConfiguration removeObjectForKey:kOOMaterialEmissionColorLegacyName];
68 : }
69 :
70 : if ((self = [super initWithName:name configuration:mutableConfiguration]))
71 : {
72 : if (diffuseSpec != nil)
73 : {
74 : _diffuseMap = [[OOTexture textureWithConfiguration:diffuseSpec] retain];
75 : if (_diffuseMap != nil) _unitsUsed++;
76 : }
77 :
78 : // Check for simplest cases, where we don't need to bake a derived emission map.
79 : if (emissionSpec != nil && illuminationSpec == nil && emissionAndIlluminationSpec == nil && emissionColor == nil)
80 : {
81 : _emissionMap = [[OOTexture textureWithConfiguration:emissionSpec extraOptions:kOOTextureExtraShrink] retain];
82 : if (_emissionMap != nil) _unitsUsed++;
83 : }
84 : else
85 : {
86 : OOCombinedEmissionMapGenerator *generator = nil;
87 :
88 : if (emissionAndIlluminationSpec != nil)
89 : {
90 : generator = [[OOCombinedEmissionMapGenerator alloc] initWithEmissionAndIlluminationMapSpec:emissionAndIlluminationSpec
91 : diffuseMap:_diffuseMap
92 : diffuseColor:diffuseColor
93 : emissionColor:emissionColor
94 : illuminationColor:illuminationColor
95 : optionsSpecifier:emissionAndIlluminationSpec];
96 : }
97 : else
98 : {
99 : generator = [[OOCombinedEmissionMapGenerator alloc] initWithEmissionMapSpec:emissionSpec
100 : emissionColor:emissionColor
101 : diffuseMap:_diffuseMap
102 : diffuseColor:diffuseColor
103 : illuminationMapSpec:illuminationSpec
104 : illuminationColor:illuminationColor
105 : optionsSpecifier:emissionSpec ?: illuminationSpec];
106 : }
107 :
108 : _emissionMap = [[OOTexture textureWithGenerator:[generator autorelease]] retain];
109 : if (_emissionMap != nil) _unitsUsed++;
110 : }
111 : }
112 :
113 : return self;
114 : }
115 :
116 :
117 : - (void) dealloc
118 : {
119 : [self willDealloc];
120 :
121 : DESTROY(_diffuseMap);
122 : DESTROY(_emissionMap);
123 :
124 : [super dealloc];
125 : }
126 :
127 :
128 : - (NSString *) descriptionComponents
129 : {
130 : NSMutableArray *bits = [NSMutableArray array];
131 : if (_diffuseMap) [bits addObject:[NSString stringWithFormat:@"diffuse map: %@", [_diffuseMap shortDescription]]];
132 : if (_emissionMap) [bits addObject:[NSString stringWithFormat:@"emission map: %@", [_emissionMap shortDescription]]];
133 :
134 : NSString *result = [super descriptionComponents];
135 : if ([bits count] > 0) result = [result stringByAppendingFormat:@" - %@", [bits componentsJoinedByString:@","]];
136 : return result;
137 : }
138 :
139 :
140 : - (NSUInteger) textureUnitCount
141 : {
142 : return _unitsUsed;
143 : }
144 :
145 :
146 : - (NSUInteger) countOfTextureUnitsWithBaseCoordinates
147 : {
148 : return _unitsUsed;
149 : }
150 :
151 :
152 : - (void) ensureFinishedLoading
153 : {
154 : [_diffuseMap ensureFinishedLoading];
155 : [_emissionMap ensureFinishedLoading];
156 : }
157 :
158 :
159 : - (void) apply
160 : {
161 : OO_ENTER_OPENGL();
162 :
163 : [super apply];
164 :
165 : GLenum textureUnit = GL_TEXTURE0_ARB;
166 :
167 : if (_diffuseMap != nil)
168 : {
169 : OOGL(glActiveTextureARB(textureUnit++));
170 : OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB));
171 : OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE));
172 : [_diffuseMap apply];
173 : }
174 :
175 : if (_emissionMap != nil)
176 : {
177 : OOGL(glActiveTextureARB(textureUnit++));
178 : OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB));
179 : OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD));
180 : [_emissionMap apply];
181 : }
182 :
183 : NSAssert2(textureUnit - GL_TEXTURE0_ARB == _unitsUsed, @"OOMultiTextureMaterial texture unit count invalid (expected %lu, actually using %u)", _unitsUsed, textureUnit - GL_TEXTURE0_ARB);
184 :
185 : if (textureUnit > GL_TEXTURE1_ARB)
186 : {
187 : OOGL(glActiveTextureARB(GL_TEXTURE0_ARB));
188 : }
189 : }
190 :
191 :
192 : - (void) unapplyWithNext:(OOMaterial *)next
193 : {
194 : OO_ENTER_OPENGL();
195 :
196 : [super unapplyWithNext:next];
197 :
198 : NSUInteger i;
199 : i = [next isKindOfClass:[OOMultiTextureMaterial class]] ? [(OOMultiTextureMaterial *)next textureUnitCount] : 0;
200 : for (; i != _unitsUsed; ++i)
201 : {
202 : OOGL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
203 : [OOTexture applyNone];
204 : OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
205 : }
206 : OOGL(glActiveTextureARB(GL_TEXTURE0_ARB));
207 : }
208 :
209 :
210 : #ifndef NDEBUG
211 : - (NSSet *) allTextures
212 : {
213 : if (_diffuseMap == nil) return [NSSet setWithObject:_emissionMap];
214 : return [NSSet setWithObjects:_diffuseMap, _emissionMap, nil];
215 : }
216 : #endif
217 :
218 : @end
219 :
220 : #endif /* OO_MULTITEXTURE */
|